diff options
Diffstat (limited to 'compiler')
19 files changed, 221 insertions, 167 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 8e748aaa58b..5a79cf68f11 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -679,12 +679,12 @@ where continue; } - if let Some((_, span)) = &depr { - struct_span_err!(diagnostic, attr.span, E0550, "multiple deprecated attributes") - .span_label(attr.span, "repeated deprecation attribute") - .span_label(*span, "first deprecation attribute") + // FIXME(jhpratt) remove this eventually + if attr.has_name(sym::rustc_deprecated) { + diagnostic + .struct_span_err(attr.span, "`#[rustc_deprecated]` has been removed") + .help("use `#[deprecated]` instead") .emit(); - break; } let Some(meta) = attr.meta() else { @@ -742,12 +742,24 @@ where continue 'outer; } } - // FIXME(jhpratt) remove this after a bootstrap occurs. Emitting an - // error specific to the renaming would be a good idea as well. + // FIXME(jhpratt) remove this eventually sym::reason if attr.has_name(sym::rustc_deprecated) => { if !get(mi, &mut note) { continue 'outer; } + + let mut diag = diagnostic + .struct_span_err(mi.span, "`reason` has been renamed"); + match note { + Some(note) => diag.span_suggestion( + mi.span, + "use `note` instead", + format!("note = \"{note}\""), + Applicability::MachineApplicable, + ), + None => diag.span_help(mi.span, "use `note` instead"), + }; + diag.emit(); } sym::suggestion => { if !sess.features_untracked().deprecated_suggestion { diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 1052d588fad..f88538f61ec 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -60,9 +60,9 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { let mut rpo = traversal::reverse_postorder(body); let ccx = ConstCx::new(tcx, body); - let (temps, all_candidates) = collect_temps_and_candidates(&ccx, &mut rpo); + let (mut temps, all_candidates) = collect_temps_and_candidates(&ccx, &mut rpo); - let promotable_candidates = validate_candidates(&ccx, &temps, &all_candidates); + let promotable_candidates = validate_candidates(&ccx, &mut temps, &all_candidates); let promoted = promote_candidates(body, tcx, temps, promotable_candidates); self.promoted_fragments.set(promoted); @@ -77,7 +77,7 @@ pub enum TempState { /// One direct assignment and any number of direct uses. /// A borrow of this temp is promotable if the assigned /// value is qualified as constant. - Defined { location: Location, uses: usize }, + Defined { location: Location, uses: usize, valid: Result<(), ()> }, /// Any other combination of assignments/uses. Unpromotable, /// This temp was part of an rvalue which got extracted @@ -133,7 +133,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { match context { PlaceContext::MutatingUse(MutatingUseContext::Store) | PlaceContext::MutatingUse(MutatingUseContext::Call) => { - *temp = TempState::Defined { location, uses: 0 }; + *temp = TempState::Defined { location, uses: 0, valid: Err(()) }; return; } _ => { /* mark as unpromotable below */ } @@ -188,7 +188,7 @@ pub fn collect_temps_and_candidates<'tcx>( /// This wraps an `Item`, and has access to all fields of that `Item` via `Deref` coercion. struct Validator<'a, 'tcx> { ccx: &'a ConstCx<'a, 'tcx>, - temps: &'a IndexVec<Local, TempState>, + temps: &'a mut IndexVec<Local, TempState>, } impl<'a, 'tcx> std::ops::Deref for Validator<'a, 'tcx> { @@ -202,7 +202,7 @@ impl<'a, 'tcx> std::ops::Deref for Validator<'a, 'tcx> { struct Unpromotable; impl<'tcx> Validator<'_, 'tcx> { - fn validate_candidate(&self, candidate: Candidate) -> Result<(), Unpromotable> { + fn validate_candidate(&mut self, candidate: Candidate) -> Result<(), Unpromotable> { let loc = candidate.location; let statement = &self.body[loc.block].statements[loc.statement_index]; match &statement.kind { @@ -234,7 +234,7 @@ impl<'tcx> Validator<'_, 'tcx> { } // FIXME(eddyb) maybe cache this? - fn qualif_local<Q: qualifs::Qualif>(&self, local: Local) -> bool { + fn qualif_local<Q: qualifs::Qualif>(&mut self, local: Local) -> bool { if let TempState::Defined { location: loc, .. } = self.temps[local] { let num_stmts = self.body[loc.block].statements.len(); @@ -272,40 +272,50 @@ impl<'tcx> Validator<'_, 'tcx> { } } - // FIXME(eddyb) maybe cache this? - fn validate_local(&self, local: Local) -> Result<(), Unpromotable> { - if let TempState::Defined { location: loc, .. } = self.temps[local] { - let block = &self.body[loc.block]; - let num_stmts = block.statements.len(); - - if loc.statement_index < num_stmts { - let statement = &block.statements[loc.statement_index]; - match &statement.kind { - StatementKind::Assign(box (_, rhs)) => self.validate_rvalue(rhs), - _ => { - span_bug!( - statement.source_info.span, - "{:?} is not an assignment", - statement - ); - } - } - } else { - let terminator = block.terminator(); - match &terminator.kind { - TerminatorKind::Call { func, args, .. } => self.validate_call(func, args), - TerminatorKind::Yield { .. } => Err(Unpromotable), - kind => { - span_bug!(terminator.source_info.span, "{:?} not promotable", kind); + fn validate_local(&mut self, local: Local) -> Result<(), Unpromotable> { + if let TempState::Defined { location: loc, uses, valid } = self.temps[local] { + valid.or_else(|_| { + let ok = { + let block = &self.body[loc.block]; + let num_stmts = block.statements.len(); + + if loc.statement_index < num_stmts { + let statement = &block.statements[loc.statement_index]; + match &statement.kind { + StatementKind::Assign(box (_, rhs)) => self.validate_rvalue(rhs), + _ => { + span_bug!( + statement.source_info.span, + "{:?} is not an assignment", + statement + ); + } + } + } else { + let terminator = block.terminator(); + match &terminator.kind { + TerminatorKind::Call { func, args, .. } => { + self.validate_call(func, args) + } + TerminatorKind::Yield { .. } => Err(Unpromotable), + kind => { + span_bug!(terminator.source_info.span, "{:?} not promotable", kind); + } + } } - } - } + }; + self.temps[local] = match ok { + Ok(()) => TempState::Defined { location: loc, uses, valid: Ok(()) }, + Err(_) => TempState::Unpromotable, + }; + ok + }) } else { Err(Unpromotable) } } - fn validate_place(&self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> { + fn validate_place(&mut self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> { match place.last_projection() { None => self.validate_local(place.local), Some((place_base, elem)) => { @@ -417,7 +427,7 @@ impl<'tcx> Validator<'_, 'tcx> { } } - fn validate_operand(&self, operand: &Operand<'tcx>) -> Result<(), Unpromotable> { + fn validate_operand(&mut self, operand: &Operand<'tcx>) -> Result<(), Unpromotable> { match operand { Operand::Copy(place) | Operand::Move(place) => self.validate_place(place.as_ref()), @@ -447,7 +457,7 @@ impl<'tcx> Validator<'_, 'tcx> { } } - fn validate_ref(&self, kind: BorrowKind, place: &Place<'tcx>) -> Result<(), Unpromotable> { + fn validate_ref(&mut self, kind: BorrowKind, place: &Place<'tcx>) -> Result<(), Unpromotable> { match kind { // Reject these borrow types just to be safe. // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase. @@ -480,7 +490,7 @@ impl<'tcx> Validator<'_, 'tcx> { Ok(()) } - fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> { + fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> { match rvalue { Rvalue::Use(operand) | Rvalue::Repeat(operand, _) => { self.validate_operand(operand)?; @@ -623,7 +633,7 @@ impl<'tcx> Validator<'_, 'tcx> { } fn validate_call( - &self, + &mut self, callee: &Operand<'tcx>, args: &[Operand<'tcx>], ) -> Result<(), Unpromotable> { @@ -665,10 +675,10 @@ impl<'tcx> Validator<'_, 'tcx> { // FIXME(eddyb) remove the differences for promotability in `static`, `const`, `const fn`. pub fn validate_candidates( ccx: &ConstCx<'_, '_>, - temps: &IndexVec<Local, TempState>, + temps: &mut IndexVec<Local, TempState>, candidates: &[Candidate], ) -> Vec<Candidate> { - let validator = Validator { ccx, temps }; + let mut validator = Validator { ccx, temps }; candidates .iter() @@ -720,7 +730,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { fn promote_temp(&mut self, temp: Local) -> Local { let old_keep_original = self.keep_original; let loc = match self.temps[temp] { - TempState::Defined { location, uses } if uses > 0 => { + TempState::Defined { location, uses, .. } if uses > 0 => { if uses > 1 { self.keep_original = true; } diff --git a/compiler/rustc_error_codes/src/error_codes/E0539.md b/compiler/rustc_error_codes/src/error_codes/E0539.md index df2d7d910bb..c53d60a5f47 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0539.md +++ b/compiler/rustc_error_codes/src/error_codes/E0539.md @@ -6,7 +6,7 @@ Erroneous code example: #![feature(staged_api)] #![stable(since = "1.0.0", feature = "test")] -#[rustc_deprecated(reason)] // error! +#[deprecated(note)] // error! #[unstable(feature = "deprecated_fn", issue = "123")] fn deprecated() {} @@ -30,7 +30,7 @@ To fix these issues you need to give required key-value pairs. #![feature(staged_api)] #![stable(since = "1.0.0", feature = "test")] -#[rustc_deprecated(since = "1.39.0", reason = "reason")] // ok! +#[deprecated(since = "1.39.0", note = "reason")] // ok! #[unstable(feature = "deprecated_fn", issue = "123")] fn deprecated() {} diff --git a/compiler/rustc_error_codes/src/error_codes/E0542.md b/compiler/rustc_error_codes/src/error_codes/E0542.md index 7fecfeaa57c..c69e574179b 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0542.md +++ b/compiler/rustc_error_codes/src/error_codes/E0542.md @@ -13,8 +13,8 @@ fn _stable_fn() {} const fn _stable_const_fn() {} #[stable(feature = "_deprecated_fn", since = "0.1.0")] -#[rustc_deprecated( - reason = "explanation for deprecation" +#[deprecated( + note = "explanation for deprecation" )] // invalid fn _deprecated_fn() {} ``` @@ -32,9 +32,9 @@ fn _stable_fn() {} const fn _stable_const_fn() {} #[stable(feature = "_deprecated_fn", since = "0.1.0")] -#[rustc_deprecated( +#[deprecated( since = "1.0.0", - reason = "explanation for deprecation" + note = "explanation for deprecation" )] // ok! fn _deprecated_fn() {} ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0543.md b/compiler/rustc_error_codes/src/error_codes/E0543.md index ba26f92e89f..d0b2e2f7a7d 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0543.md +++ b/compiler/rustc_error_codes/src/error_codes/E0543.md @@ -1,4 +1,4 @@ -The `reason` value is missing in a stability attribute. +The `note` value is missing in a stability attribute. Erroneous code example: @@ -7,22 +7,22 @@ Erroneous code example: #![stable(since = "1.0.0", feature = "test")] #[stable(since = "0.1.0", feature = "_deprecated_fn")] -#[rustc_deprecated( +#[deprecated( since = "1.0.0" )] // invalid fn _deprecated_fn() {} ``` -To fix this issue, you need to provide the `reason` field. Example: +To fix this issue, you need to provide the `note` field. Example: ``` #![feature(staged_api)] #![stable(since = "1.0.0", feature = "test")] #[stable(since = "0.1.0", feature = "_deprecated_fn")] -#[rustc_deprecated( +#[deprecated( since = "1.0.0", - reason = "explanation for deprecation" + note = "explanation for deprecation" )] // ok! fn _deprecated_fn() {} ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0549.md b/compiler/rustc_error_codes/src/error_codes/E0549.md index d4b78e7e0d6..70e458a9867 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0549.md +++ b/compiler/rustc_error_codes/src/error_codes/E0549.md @@ -1,5 +1,5 @@ -A `rustc_deprecated` attribute wasn't paired with a `stable`/`unstable` -attribute. +A `deprecated` attribute wasn't paired with a `stable`/`unstable` attribute with +`#![feature(staged_api)]` enabled. Erroneous code example: @@ -7,9 +7,9 @@ Erroneous code example: #![feature(staged_api)] #![stable(since = "1.0.0", feature = "test")] -#[rustc_deprecated( +#[deprecated( since = "1.0.1", - reason = "explanation for deprecation" + note = "explanation for deprecation" )] // invalid fn _deprecated_fn() {} ``` @@ -22,9 +22,9 @@ Example: #![stable(since = "1.0.0", feature = "test")] #[stable(since = "1.0.0", feature = "test")] -#[rustc_deprecated( +#[deprecated( since = "1.0.1", - reason = "explanation for deprecation" + note = "explanation for deprecation" )] // ok! fn _deprecated_fn() {} ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0550.md b/compiler/rustc_error_codes/src/error_codes/E0550.md index 1487d701847..6aac5c969d2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0550.md +++ b/compiler/rustc_error_codes/src/error_codes/E0550.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler + More than one `deprecated` attribute has been put on an item. Erroneous code example: -```compile_fail,E0550 +```compile_fail #[deprecated(note = "because why not?")] #[deprecated(note = "right?")] // error! fn the_banished() {} diff --git a/compiler/rustc_error_codes/src/error_codes/E0734.md b/compiler/rustc_error_codes/src/error_codes/E0734.md index 4b8e89a7060..b912061ec42 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0734.md +++ b/compiler/rustc_error_codes/src/error_codes/E0734.md @@ -3,7 +3,6 @@ A stability attribute has been used outside of the standard library. Erroneous code example: ```compile_fail,E0734 -#[rustc_deprecated(since = "b", reason = "text")] // invalid #[stable(feature = "a", since = "b")] // invalid #[unstable(feature = "b", issue = "none")] // invalid fn foo(){} diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 33d2e82b24a..c5f42aa7af7 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -304,8 +304,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, NameValueStr: "reason" ), - // This has special duplicate handling in E0550 to handle duplicates with rustc_deprecated - DuplicatesOk + ErrorFollowing ), // Crate properties: @@ -469,10 +468,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== ungated!(feature, CrateLevel, template!(List: "name1, name2, ..."), DuplicatesOk), - // DuplicatesOk since it has its own validation + // FIXME(jhpratt) remove this eventually ungated!( rustc_deprecated, Normal, - template!(List: r#"since = "version", note = "...""#), DuplicatesOk // See E0550 + template!(List: r#"since = "version", note = "...""#), ErrorFollowing ), // DuplicatesOk since it has its own validation ungated!( diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index b8ba65adaa8..565ec4e5ab9 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2201,13 +2201,12 @@ declare_lint! { /// used by user code. /// /// This lint is only enabled in the standard library. It works with the - /// use of `#[rustc_deprecated]` with a `since` field of a version in the - /// future. This allows something to be marked as deprecated in a future - /// version, and then this lint will ensure that the item is no longer - /// used in the standard library. See the [stability documentation] for - /// more details. + /// use of `#[deprecated]` with a `since` field of a version in the future. + /// This allows something to be marked as deprecated in a future version, + /// and then this lint will ensure that the item is no longer used in the + /// standard library. See the [stability documentation] for more details. /// - /// [stability documentation]: https://rustc-dev-guide.rust-lang.org/stability.html#rustc_deprecated + /// [stability documentation]: https://rustc-dev-guide.rust-lang.org/stability.html#deprecated pub DEPRECATED_IN_FUTURE, Allow, "detects use of items that will be deprecated in a future version", diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 32041143240..6918046390e 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -118,8 +118,7 @@ pub fn deprecation_in_effect(depr: &Deprecation) -> bool { } if !is_since_rustc_version { - // The `since` field doesn't have semantic purpose in the stable `deprecated` - // attribute, only in `rustc_deprecated`. + // The `since` field doesn't have semantic purpose without `#![staged_api]`. return true; } @@ -336,7 +335,7 @@ impl<'tcx> TyCtxt<'tcx> { // topmost deprecation. For example, if a struct is deprecated, // the use of a field won't be linted. // - // #[rustc_deprecated] however wants to emit down the whole + // With #![staged_api], we want to emit down the whole // hierarchy. let depr_attr = &depr_entry.attr; if !skip || depr_attr.is_since_rustc_version { diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 5063420e975..5b1fb708729 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -10,7 +10,7 @@ use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::DUMMY_SP; use smallvec::SmallVec; use core::intrinsics; @@ -498,34 +498,14 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> { } } -/////////////////////////////////////////////////////////////////////////// -// Public trait `Subst` -// -// Just call `foo.subst(tcx, substs)` to perform a substitution across -// `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when -// there is more information available (for better errors). - +// Just call `foo.subst(tcx, substs)` to perform a substitution across `foo`. pub trait Subst<'tcx>: Sized { - fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> Self { - self.subst_spanned(tcx, substs, None) - } - - fn subst_spanned( - self, - tcx: TyCtxt<'tcx>, - substs: &[GenericArg<'tcx>], - span: Option<Span>, - ) -> Self; + fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> Self; } impl<'tcx, T: TypeFoldable<'tcx>> Subst<'tcx> for T { - fn subst_spanned( - self, - tcx: TyCtxt<'tcx>, - substs: &[GenericArg<'tcx>], - span: Option<Span>, - ) -> T { - let mut folder = SubstFolder { tcx, substs, span, binders_passed: 0 }; + fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T { + let mut folder = SubstFolder { tcx, substs, binders_passed: 0 }; self.fold_with(&mut folder) } } @@ -537,9 +517,6 @@ struct SubstFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, substs: &'a [GenericArg<'tcx>], - /// The location for which the substitution is performed, if available. - span: Option<Span>, - /// Number of region binders we have passed through while doing the substitution binders_passed: u32, } @@ -571,13 +548,12 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { match rk { Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), _ => { - let span = self.span.unwrap_or(DUMMY_SP); let msg = format!( "Region parameter out of range \ when substituting in region {} (index={})", data.name, data.index ); - span_bug!(span, "{}", msg); + span_bug!(DUMMY_SP, "{}", msg); } } } @@ -617,9 +593,8 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { let ty = match opt_ty { Some(GenericArgKind::Type(ty)) => ty, Some(kind) => { - let span = self.span.unwrap_or(DUMMY_SP); span_bug!( - span, + DUMMY_SP, "expected type for `{:?}` ({:?}/{}) but found {:?} \ when substituting, substs={:?}", p, @@ -630,9 +605,8 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { ); } None => { - let span = self.span.unwrap_or(DUMMY_SP); span_bug!( - span, + DUMMY_SP, "type parameter `{:?}` ({:?}/{}) out of range \ when substituting, substs={:?}", p, @@ -652,9 +626,8 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { let ct = match opt_ct { Some(GenericArgKind::Const(ct)) => ct, Some(kind) => { - let span = self.span.unwrap_or(DUMMY_SP); span_bug!( - span, + DUMMY_SP, "expected const for `{:?}` ({:?}/{}) but found {:?} \ when substituting substs={:?}", p, @@ -665,9 +638,8 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { ); } None => { - let span = self.span.unwrap_or(DUMMY_SP); span_bug!( - span, + DUMMY_SP, "const parameter `{:?}` ({:?}/{}) out of range \ when substituting substs={:?}", p, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index b297012f19f..2b0fa57cba8 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -4,7 +4,8 @@ //! conflicts between multiple such attributes attached to the same //! item. -use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; +use rustc_ast::tokenstream::DelimSpan; +use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MacArgs, MetaItemKind, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; @@ -810,6 +811,68 @@ impl CheckAttrVisitor<'_> { } } + /// Checks `#[doc(hidden)]` attributes. Returns `true` if valid. + fn check_doc_hidden( + &self, + attr: &Attribute, + meta_index: usize, + meta: &NestedMetaItem, + hir_id: HirId, + target: Target, + ) -> bool { + if let Target::AssocConst + | Target::AssocTy + | Target::Method(MethodKind::Trait { body: true }) = target + { + let parent_hir_id = self.tcx.hir().get_parent_item(hir_id); + let containing_item = self.tcx.hir().expect_item(parent_hir_id); + + if Target::from_item(containing_item) == Target::Impl { + let meta_items = attr.meta_item_list().unwrap(); + + let (span, replacement_span) = if meta_items.len() == 1 { + (attr.span, attr.span) + } else { + let meta_span = meta.span(); + ( + meta_span, + meta_span.until(match meta_items.get(meta_index + 1) { + Some(next_item) => next_item.span(), + None => match attr.get_normal_item().args { + MacArgs::Delimited(DelimSpan { close, .. }, ..) => close, + _ => unreachable!(), + }, + }), + ) + }; + + // FIXME: #[doc(hidden)] was previously erroneously allowed on trait impl items, + // so for backward compatibility only emit a warning and do not mark it as invalid. + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| { + lint.build("`#[doc(hidden)]` is ignored on trait impl items") + .warn( + "this was previously accepted by the compiler but is \ + being phased out; it will become a hard error in \ + a future release!", + ) + .note( + "whether the impl item is `doc(hidden)` or not \ + entirely depends on the corresponding trait item", + ) + .span_suggestion( + replacement_span, + "remove this attribute", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + }); + } + } + + true + } + /// Checks that an attribute is *not* used at the crate level. Returns `true` if valid. fn check_attr_not_crate_level( &self, @@ -928,7 +991,7 @@ impl CheckAttrVisitor<'_> { let mut is_valid = true; if let Some(mi) = attr.meta() && let Some(list) = mi.meta_item_list() { - for meta in list { + for (meta_index, meta) in list.into_iter().enumerate() { if let Some(i_meta) = meta.meta_item() { match i_meta.name_or_empty() { sym::alias @@ -969,6 +1032,15 @@ impl CheckAttrVisitor<'_> { is_valid = false; } + sym::hidden if !self.check_doc_hidden(attr, + meta_index, + meta, + hir_id, + target, + ) => { + is_valid = false; + } + // no_default_passes: deprecated // passes: deprecated // plugins: removed, but rustdoc warns about it itself diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 93f6b4a6b5a..3c1676b1aac 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -523,11 +523,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.astconv .normalize_ty( self.span, - tcx.at(self.span).type_of(param.def_id).subst_spanned( - tcx, - substs, - Some(self.span), - ), + tcx.at(self.span).type_of(param.def_id).subst(tcx, substs), ) .into() } @@ -547,9 +543,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericParamDefKind::Const { has_default } => { let ty = tcx.at(self.span).type_of(param.def_id); if !infer_args && has_default { - tcx.const_param_default(param.def_id) - .subst_spanned(tcx, substs.unwrap(), Some(self.span)) - .into() + tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into() } else { if infer_args { self.astconv.ct_infer(ty, Some(param), self.span).into() diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index a1e8d2040dd..f3a5b9f13dd 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -44,7 +44,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::error::TypeError::{FieldMisMatch, Sorts}; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable}; +use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TypeFoldable}; use rustc_session::parse::feature_err; use rustc_span::hygiene::DesugaringKind; use rustc_span::lev_distance::find_best_match_for_name; @@ -2034,17 +2034,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base: &'tcx hir::Expr<'tcx>, def_id: DefId, ) { - let local_id = def_id.expect_local(); - let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_id); - let node = self.tcx.hir().get(hir_id); - - if let Some(fields) = node.tuple_fields() { - let kind = match self.tcx.opt_def_kind(local_id) { - Some(DefKind::Ctor(of, _)) => of, - _ => return, - }; + if let Some(local_id) = def_id.as_local() { + let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_id); + let node = self.tcx.hir().get(hir_id); + + if let Some(fields) = node.tuple_fields() { + let kind = match self.tcx.opt_def_kind(local_id) { + Some(DefKind::Ctor(of, _)) => of, + _ => return, + }; - suggest_call_constructor(base.span, kind, fields.len(), err); + suggest_call_constructor(base.span, kind, fields.len(), err); + } + } else { + // The logic here isn't smart but `associated_item_def_ids` + // doesn't work nicely on local. + if let DefKind::Ctor(of, _) = self.tcx.def_kind(def_id) { + let parent_def_id = self.tcx.parent(def_id); + let fields = self.tcx.associated_item_def_ids(parent_def_id); + suggest_call_constructor(base.span, of, fields.len(), err); + } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 93b0edb84c0..d824c1d7cf2 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1403,10 +1403,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // is missing. let default = tcx.type_of(param.def_id); self.fcx - .normalize_ty( - self.span, - default.subst_spanned(tcx, substs.unwrap(), Some(self.span)), - ) + .normalize_ty(self.span, default.subst(tcx, substs.unwrap())) .into() } else { // If no type arguments were provided, we have to infer them. @@ -1418,9 +1415,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } GenericParamDefKind::Const { has_default } => { if !infer_args && has_default { - tcx.const_param_default(param.def_id) - .subst_spanned(tcx, substs.unwrap(), Some(self.span)) - .into() + tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into() } else { self.fcx.var_for_def(self.span, param) } diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index bc0fa916556..1b619776b85 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -462,19 +462,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let sig = self.tcx.fn_sig(def_id); - // Instantiate late-bound regions and substitute the trait - // parameters into the method type to get the actual method type. - // - // N.B., instantiate late-bound regions first so that - // `instantiate_type_scheme` can normalize associated types that - // may reference those regions. - let method_sig = self.replace_bound_vars_with_fresh_vars(sig); - debug!("late-bound lifetimes from method instantiated, method_sig={:?}", method_sig); + let sig = sig.subst(self.tcx, all_substs); + debug!("type scheme substituted, sig={:?}", sig); - let method_sig = method_sig.subst(self.tcx, all_substs); - debug!("type scheme substituted, method_sig={:?}", method_sig); + let sig = self.replace_bound_vars_with_fresh_vars(sig); + debug!("late-bound lifetimes from method instantiated, sig={:?}", sig); - (method_sig, method_predicates) + (sig, method_predicates) } fn add_obligations( diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 8137d702921..1dd5e45fdc1 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -461,8 +461,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `instantiate_type_scheme` can normalize associated types that // may reference those regions. let fn_sig = tcx.fn_sig(def_id); - let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig).0; let fn_sig = fn_sig.subst(self.tcx, substs); + let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig).0; let InferOk { value, obligations: o } = if is_op { self.normalize_op_associated_types_in_as_infer_ok(span, fn_sig, opt_input_expr) diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index c7d0f61c601..c28ab9fa1ee 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -1784,12 +1784,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let generics = self.tcx.generics_of(method); assert_eq!(substs.len(), generics.parent_count as usize); - // Erase any late-bound regions from the method and substitute - // in the values from the substitution. - let xform_fn_sig = self.erase_late_bound_regions(fn_sig); - - if generics.params.is_empty() { - xform_fn_sig.subst(self.tcx, substs) + let xform_fn_sig = if generics.params.is_empty() { + fn_sig.subst(self.tcx, substs) } else { let substs = InternalSubsts::for_item(self.tcx, method, |param, _| { let i = param.index as usize; @@ -1807,8 +1803,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } }); - xform_fn_sig.subst(self.tcx, substs) - } + fn_sig.subst(self.tcx, substs) + }; + + self.erase_late_bound_regions(xform_fn_sig) } /// Gets the type of an impl and generate substitutions with placeholders. |
