From 58c6591cde1b8a54dbc1ad1b7ac64133835ec154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Oct 2019 16:20:42 -0700 Subject: [PATCH 01/22] Point at associated type for some obligations --- src/librustc/traits/error_reporting.rs | 6 ++ src/librustc/traits/mod.rs | 2 + src/librustc/traits/structural_impls.rs | 1 + src/librustc/ty/mod.rs | 1 + src/librustc/ty/wf.rs | 64 +++++++++++++------ src/librustc_typeck/check/wfcheck.rs | 23 ++++--- .../ui/issues/issue-43784-associated-type.rs | 4 +- .../issues/issue-43784-associated-type.stderr | 17 +++-- src/test/ui/traits/cycle-cache-err-60010.rs | 4 +- .../ui/traits/cycle-cache-err-60010.stderr | 12 +++- 10 files changed, 93 insertions(+), 41 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index daa4a215a238a..7ab907701bf04 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2199,6 +2199,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } } + ObligationCauseCode::AssocTypeBound(impl_span, orig) => { + err.span_label(orig, "associated type defined here"); + if let Some(sp) = impl_span { + err.span_label(sp, "in this `impl` item"); + } + } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index d96330bf0a9b4..9640a8a29d1e4 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -268,6 +268,8 @@ pub enum ObligationCauseCode<'tcx> { /// #[feature(trivial_bounds)] is not enabled TrivialBound, + + AssocTypeBound(/*impl*/ Option, /*original*/ Span), } // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index dab62a6bcb5b1..f81d4b3ca3049 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -544,6 +544,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::MethodReceiver => Some(super::MethodReceiver), super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), super::TrivialBound => Some(super::TrivialBound), + super::AssocTypeBound(impl_sp, sp) => Some(super::AssocTypeBound(impl_sp, sp)), } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d377b7328e80b..d81f5e4070114 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3139,6 +3139,7 @@ impl<'tcx> TyCtxt<'tcx> { } } +#[derive(Clone)] pub struct AssocItemsIterator<'tcx> { tcx: TyCtxt<'tcx>, def_ids: &'tcx [DefId], diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index ecb075e30b14d..ce92fd82761bb 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -22,11 +22,14 @@ pub fn obligations<'a, 'tcx>( ty: Ty<'tcx>, span: Span, ) -> Option>> { - let mut wf = WfPredicates { infcx, - param_env, - body_id, - span, - out: vec![] }; + let mut wf = WfPredicates { + infcx, + param_env, + body_id, + span, + out: vec![], + item: None, + }; if wf.compute(ty) { debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out); let result = wf.normalize(); @@ -47,8 +50,9 @@ pub fn trait_obligations<'a, 'tcx>( body_id: hir::HirId, trait_ref: &ty::TraitRef<'tcx>, span: Span, + item: Option<&'tcx hir::Item>, ) -> Vec> { - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] }; + let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item }; wf.compute_trait_ref(trait_ref, Elaborate::All); wf.normalize() } @@ -60,7 +64,7 @@ pub fn predicate_obligations<'a, 'tcx>( predicate: &ty::Predicate<'tcx>, span: Span, ) -> Vec> { - let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] }; + let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None }; // (*) ok to skip binders, because wf code is prepared for it match *predicate { @@ -107,6 +111,7 @@ struct WfPredicates<'a, 'tcx> { body_id: hir::HirId, span: Span, out: Vec>, + item: Option<&'tcx hir::Item>, } /// Controls whether we "elaborate" supertraits and so forth on the WF @@ -157,33 +162,54 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { .collect() } - /// Pushes the obligations required for `trait_ref` to be WF into - /// `self.out`. + /// Pushes the obligations required for `trait_ref` to be WF into `self.out`. fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) { let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); - + let assoc_items = self.infcx.tcx.associated_items(trait_ref.def_id); let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; if let Elaborate::All = elaborate { let predicates = obligations.iter() - .map(|obligation| obligation.predicate.clone()) - .collect(); + .map(|obligation| obligation.predicate.clone()) + .collect(); let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates); + let item_span: Option = self.item.map(|i| i.span); + let item = &self.item; let implied_obligations = implied_obligations.map(|pred| { - traits::Obligation::new(cause.clone(), param_env, pred) + let mut cause = cause.clone(); + if let ty::Predicate::Trait(proj) = &pred { + if let ( + ty::Projection(ty::ProjectionTy { item_def_id, .. }), + Some(hir::ItemKind::Impl(.., bounds)), + ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind)) { + if let Some((bound, assoc_item)) = assoc_items.clone() + .filter(|i| i.def_id == *item_def_id) + .next() + .and_then(|assoc_item| bounds.iter() + .filter(|b| b.ident == assoc_item.ident) + .next() + .map(|bound| (bound, assoc_item))) + { + cause.span = bound.span; + cause.code = traits::AssocTypeBound(item_span, assoc_item.ident.span); + } + } + } + traits::Obligation::new(cause, param_env, pred) }); self.out.extend(implied_obligations); } self.out.extend(obligations); - self.out.extend( - trait_ref.substs.types() - .filter(|ty| !ty.has_escaping_bound_vars()) - .map(|ty| traits::Obligation::new(cause.clone(), - param_env, - ty::Predicate::WellFormed(ty)))); + self.out.extend(trait_ref.substs.types() + .filter(|ty| !ty.has_escaping_bound_vars()) + .map(|ty| traits::Obligation::new( + cause.clone(), + param_env, + ty::Predicate::WellFormed(ty), + ))); } /// Pushes the obligations required for `trait_ref::Item` to be WF diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 18b103960c745..b4b8d4566d577 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -430,7 +430,7 @@ fn check_item_type( fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, - item: &hir::Item, + item: &'tcx hir::Item, ast_self_ty: &hir::Ty, ast_trait_ref: &Option, ) { @@ -445,15 +445,18 @@ fn check_impl<'tcx>( // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); - let trait_ref = - fcx.normalize_associated_types_in( - ast_trait_ref.path.span, &trait_ref); - let obligations = - ty::wf::trait_obligations(fcx, - fcx.param_env, - fcx.body_id, - &trait_ref, - ast_trait_ref.path.span); + let trait_ref = fcx.normalize_associated_types_in( + ast_trait_ref.path.span, + &trait_ref, + ); + let obligations = ty::wf::trait_obligations( + fcx, + fcx.param_env, + fcx.body_id, + &trait_ref, + ast_trait_ref.path.span, + Some(item), + ); for obligation in obligations { fcx.register_predicate(obligation); } diff --git a/src/test/ui/issues/issue-43784-associated-type.rs b/src/test/ui/issues/issue-43784-associated-type.rs index fb58ad6600f7e..92083d88f1b82 100644 --- a/src/test/ui/issues/issue-43784-associated-type.rs +++ b/src/test/ui/issues/issue-43784-associated-type.rs @@ -10,8 +10,8 @@ impl Partial for T::Assoc where { } -impl Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied - type Assoc = T; +impl Complete for T { + type Assoc = T; //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied } fn main() {} diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index e91e53499ce6c..cfab66302cdca 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -1,10 +1,17 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/issue-43784-associated-type.rs:13:9 + --> $DIR/issue-43784-associated-type.rs:14:5 | -LL | impl Complete for T { - | - ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::marker::Copy` +LL | type Assoc: Partial; + | ----- associated type defined here +... +LL | / impl Complete for T { + | | - help: consider restricting this bound: `T: std::marker::Copy` +LL | | type Assoc = T; + | | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` +LL | | } + | |_- in this `impl` item + | + = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/traits/cycle-cache-err-60010.rs b/src/test/ui/traits/cycle-cache-err-60010.rs index 45aa1b3c52239..cbddef082be67 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.rs +++ b/src/test/ui/traits/cycle-cache-err-60010.rs @@ -27,8 +27,8 @@ struct SalsaStorage { _parse: >::Data, //~ ERROR overflow } -impl Database for RootDatabase { //~ ERROR overflow - type Storage = SalsaStorage; +impl Database for RootDatabase { + type Storage = SalsaStorage; //~ ERROR overflow } impl HasQueryGroup for RootDatabase {} impl Query for ParseQuery diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index 9192f7ba2e3b0..a7b8dd05527a5 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -7,10 +7,16 @@ LL | _parse: >::Data, = note: required because of the requirements on the impl of `Query` for `ParseQuery` error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase` - --> $DIR/cycle-cache-err-60010.rs:30:6 + --> $DIR/cycle-cache-err-60010.rs:31:5 | -LL | impl Database for RootDatabase { - | ^^^^^^^^ +LL | type Storage; + | ------- associated type defined here +... +LL | / impl Database for RootDatabase { +LL | | type Storage = SalsaStorage; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | | } + | |_- in this `impl` item | = note: required because of the requirements on the impl of `Query` for `ParseQuery` = note: required because it appears within the type `SalsaStorage` From 88e4e2a2089992ec6e33e29d66986f7574412dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Oct 2019 19:20:51 -0700 Subject: [PATCH 02/22] fix compile-fail test --- src/test/compile-fail/chalkify/impl_wf.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/compile-fail/chalkify/impl_wf.rs b/src/test/compile-fail/chalkify/impl_wf.rs index 96b1b2533712b..6bb4cf86e7986 100644 --- a/src/test/compile-fail/chalkify/impl_wf.rs +++ b/src/test/compile-fail/chalkify/impl_wf.rs @@ -25,6 +25,7 @@ impl Bar for Option { impl Bar for f32 { //~^ ERROR the trait bound `f32: Foo` is not satisfied type Item = f32; + //~^ ERROR the trait bound `f32: Foo` is not satisfied } trait Baz where U: Foo { } From 5b58095f68e971b952310b5a402a287f252936d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Oct 2019 19:25:34 -0700 Subject: [PATCH 03/22] Handle projection obligation errors --- src/librustc/ty/wf.rs | 43 ++++++++++++++----- .../point-at-type-on-obligation-failure-2.rs | 11 +++++ ...int-at-type-on-obligation-failure-2.stderr | 15 +++++++ .../point-at-type-on-obligation-failure.rs | 20 +++++++++ ...point-at-type-on-obligation-failure.stderr | 19 ++++++++ 5 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs create mode 100644 src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr create mode 100644 src/test/ui/associated-types/point-at-type-on-obligation-failure.rs create mode 100644 src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index ce92fd82761bb..f9abd31850527 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -164,37 +164,60 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// Pushes the obligations required for `trait_ref` to be WF into `self.out`. fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) { + let tcx = self.infcx.tcx; let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); - let assoc_items = self.infcx.tcx.associated_items(trait_ref.def_id); + let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; if let Elaborate::All = elaborate { + let trait_assoc_items = tcx.associated_items(trait_ref.def_id); + let predicates = obligations.iter() .map(|obligation| obligation.predicate.clone()) .collect(); - let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates); + let implied_obligations = traits::elaborate_predicates(tcx, predicates); let item_span: Option = self.item.map(|i| i.span); let item = &self.item; let implied_obligations = implied_obligations.map(|pred| { let mut cause = cause.clone(); - if let ty::Predicate::Trait(proj) = &pred { + match &pred { + ty::Predicate::Projection(proj) => { + if let Some(hir::ItemKind::Impl(.., impl_items)) = item.map(|i| &i.kind) { + let trait_assoc_item = tcx.associated_item(proj.projection_def_id()); + if let Some(impl_item) = impl_items.iter().filter(|item| { + item.ident == trait_assoc_item.ident + }).next() { + cause.span = impl_item.span; + cause.code = traits::AssocTypeBound( + item_span, + trait_assoc_item.ident.span, + ); + } + } + } + ty::Predicate::Trait(proj) => { if let ( ty::Projection(ty::ProjectionTy { item_def_id, .. }), - Some(hir::ItemKind::Impl(.., bounds)), + Some(hir::ItemKind::Impl(.., impl_items)), ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind)) { - if let Some((bound, assoc_item)) = assoc_items.clone() + if let Some((impl_item, trait_assoc_item)) = trait_assoc_items.clone() .filter(|i| i.def_id == *item_def_id) .next() - .and_then(|assoc_item| bounds.iter() - .filter(|b| b.ident == assoc_item.ident) + .and_then(|trait_assoc_item| impl_items.iter() + .filter(|i| i.ident == trait_assoc_item.ident) .next() - .map(|bound| (bound, assoc_item))) + .map(|impl_item| (impl_item, trait_assoc_item))) { - cause.span = bound.span; - cause.code = traits::AssocTypeBound(item_span, assoc_item.ident.span); + cause.span = impl_item.span; + cause.code = traits::AssocTypeBound( + item_span, + trait_assoc_item.ident.span, + ); + } } } + _ => {} } traits::Obligation::new(cause, param_env, pred) }); diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs new file mode 100644 index 0000000000000..9360d96f05e17 --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs @@ -0,0 +1,11 @@ +trait Bar {} + +trait Foo { + type Assoc: Bar; +} + +impl Foo for () { + type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr new file mode 100644 index 0000000000000..62bb9388633b0 --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `bool: Bar` is not satisfied + --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 + | +LL | type Assoc: Bar; + | ----- associated type defined here +... +LL | / impl Foo for () { +LL | | type Assoc = bool; + | | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` +LL | | } + | |_- in this `impl` item + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs new file mode 100644 index 0000000000000..dc43dbaf54b99 --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs @@ -0,0 +1,20 @@ +trait Bar { + type Ok; + type Sibling: Bar2; +} +trait Bar2 { + type Ok; +} + +struct Foo; +struct Foo2; + +impl Bar for Foo { + type Ok = (); //~ ERROR type mismatch resolving `::Ok == ()` + type Sibling = Foo2; +} +impl Bar2 for Foo2 { + type Ok = u32; +} + +fn main() {} diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr new file mode 100644 index 0000000000000..95e8ebdd180b0 --- /dev/null +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr @@ -0,0 +1,19 @@ +error[E0271]: type mismatch resolving `::Ok == ()` + --> $DIR/point-at-type-on-obligation-failure.rs:13:5 + | +LL | type Ok; + | -- associated type defined here +... +LL | / impl Bar for Foo { +LL | | type Ok = (); + | | ^^^^^^^^^^^^^ expected u32, found () +LL | | type Sibling = Foo2; +LL | | } + | |_- in this `impl` item + | + = note: expected type `u32` + found type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. From 0118278cdea7f07c2a9f7d75506a48cf554979e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Oct 2019 19:33:05 -0700 Subject: [PATCH 04/22] Drive-by formatting --- src/librustc/traits/error_reporting.rs | 46 +++++++++++++++++--------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 7ab907701bf04..c6bb45172a973 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -195,8 +195,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, error: &MismatchedProjectionTypes<'tcx>, ) { - let predicate = - self.resolve_vars_if_possible(&obligation.predicate); + let predicate = self.resolve_vars_if_possible(&obligation.predicate); if predicate.references_error() { return @@ -228,7 +227,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &mut obligations ); if let Err(error) = self.at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, data.ty) { + .eq(normalized_ty, data.ty) + { values = Some(infer::ValuePairs::Types(ExpectedFound { expected: normalized_ty, found: data.ty, @@ -239,13 +239,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let msg = format!("type mismatch resolving `{}`", predicate); - let error_id = (DiagnosticMessageId::ErrorId(271), - Some(obligation.cause.span), msg); + let error_id = ( + DiagnosticMessageId::ErrorId(271), + Some(obligation.cause.span), + msg, + ); let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); if fresh { let mut diag = struct_span_err!( - self.tcx.sess, obligation.cause.span, E0271, - "type mismatch resolving `{}`", predicate + self.tcx.sess, + obligation.cause.span, + E0271, + "type mismatch resolving `{}`", + predicate ); self.note_type_err(&mut diag, &obligation.cause, None, values, err); self.note_obligation_cause(&mut diag, obligation); @@ -532,23 +538,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// whose result could not be truly determined and thus we can't say /// if the program type checks or not -- and they are unusual /// occurrences in any case. - pub fn report_overflow_error(&self, - obligation: &Obligation<'tcx, T>, - suggest_increasing_limit: bool) -> ! + pub fn report_overflow_error( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! where T: fmt::Display + TypeFoldable<'tcx> { let predicate = self.resolve_vars_if_possible(&obligation.predicate); - let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275, - "overflow evaluating the requirement `{}`", - predicate); + let mut err = struct_span_err!( + self.tcx.sess, + obligation.cause.span, + E0275, + "overflow evaluating the requirement `{}`", + predicate + ); if suggest_increasing_limit { self.suggest_new_overflow_limit(&mut err); } - self.note_obligation_cause_code(&mut err, &obligation.predicate, &obligation.cause.code, - &mut vec![]); + self.note_obligation_cause_code( + &mut err, + &obligation.predicate, + &obligation.cause.code, + &mut vec![], + ); err.emit(); self.tcx.sess.abort_if_errors(); From 669a4035eff7e3cc6b295a68ce43cc342ec29ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Oct 2019 12:40:46 -0700 Subject: [PATCH 05/22] review comments: move code, fix indentation and change span --- src/librustc/ty/wf.rs | 90 +++++++++++-------- ...int-at-type-on-obligation-failure-2.stderr | 13 ++- ...point-at-type-on-obligation-failure.stderr | 14 ++- .../issues/issue-43784-associated-type.stderr | 16 ++-- .../ui/traits/cycle-cache-err-60010.stderr | 13 ++- 5 files changed, 77 insertions(+), 69 deletions(-) diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index f9abd31850527..84bcec6bd199f 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -170,55 +170,67 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; - if let Elaborate::All = elaborate { - let trait_assoc_items = tcx.associated_items(trait_ref.def_id); - - let predicates = obligations.iter() - .map(|obligation| obligation.predicate.clone()) - .collect(); - let implied_obligations = traits::elaborate_predicates(tcx, predicates); - let item_span: Option = self.item.map(|i| i.span); - let item = &self.item; - let implied_obligations = implied_obligations.map(|pred| { - let mut cause = cause.clone(); - match &pred { - ty::Predicate::Projection(proj) => { - if let Some(hir::ItemKind::Impl(.., impl_items)) = item.map(|i| &i.kind) { - let trait_assoc_item = tcx.associated_item(proj.projection_def_id()); - if let Some(impl_item) = impl_items.iter().filter(|item| { - item.ident == trait_assoc_item.ident - }).next() { - cause.span = impl_item.span; - cause.code = traits::AssocTypeBound( - item_span, - trait_assoc_item.ident.span, - ); - } + let item = &self.item; + let extend_cause_with_original_assoc_item_obligation = | + cause: &mut traits::ObligationCause<'_>, + pred: &ty::Predicate<'_>, + trait_assoc_items: ty::AssocItemsIterator<'_>, + | { + let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span)); + match pred { + ty::Predicate::Projection(proj) => { + if let Some(hir::ItemKind::Impl(.., impl_items)) = item.map(|i| &i.kind) { + let trait_assoc_item = tcx.associated_item(proj.projection_def_id()); + if let Some(impl_item) = impl_items.iter().filter(|item| { + item.ident == trait_assoc_item.ident + }).next() { + cause.span = impl_item.span; + cause.code = traits::AssocTypeBound( + item_span, + trait_assoc_item.ident.span, + ); } } - ty::Predicate::Trait(proj) => { + } + ty::Predicate::Trait(proj) => { if let ( ty::Projection(ty::ProjectionTy { item_def_id, .. }), - Some(hir::ItemKind::Impl(.., impl_items)), - ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind)) { - if let Some((impl_item, trait_assoc_item)) = trait_assoc_items.clone() + Some(hir::ItemKind::Impl(.., impl_items)), + ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind)) { + if let Some((impl_item, trait_assoc_item)) = trait_assoc_items .filter(|i| i.def_id == *item_def_id) .next() - .and_then(|trait_assoc_item| impl_items.iter() - .filter(|i| i.ident == trait_assoc_item.ident) - .next() - .map(|impl_item| (impl_item, trait_assoc_item))) + .and_then(|trait_assoc_item| impl_items.iter() + .filter(|i| i.ident == trait_assoc_item.ident) + .next() + .map(|impl_item| (impl_item, trait_assoc_item))) { - cause.span = impl_item.span; - cause.code = traits::AssocTypeBound( - item_span, - trait_assoc_item.ident.span, - ); - } + cause.span = impl_item.span; + cause.code = traits::AssocTypeBound( + item_span, + trait_assoc_item.ident.span, + ); } } - _ => {} } + _ => {} + } + }; + + if let Elaborate::All = elaborate { + let trait_assoc_items = tcx.associated_items(trait_ref.def_id); + + let predicates = obligations.iter() + .map(|obligation| obligation.predicate.clone()) + .collect(); + let implied_obligations = traits::elaborate_predicates(tcx, predicates); + let implied_obligations = implied_obligations.map(|pred| { + let mut cause = cause.clone(); + extend_cause_with_original_assoc_item_obligation( + &mut cause, + &pred, + trait_assoc_items.clone(), + ); traits::Obligation::new(cause, param_env, pred) }); self.out.extend(implied_obligations); diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr index 62bb9388633b0..f1a2e343a7ec3 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr @@ -1,14 +1,13 @@ error[E0277]: the trait bound `bool: Bar` is not satisfied --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 | -LL | type Assoc: Bar; - | ----- associated type defined here +LL | type Assoc: Bar; + | ----- associated type defined here ... -LL | / impl Foo for () { -LL | | type Assoc = bool; - | | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` -LL | | } - | |_- in this `impl` item +LL | impl Foo for () { + | --------------- in this `impl` item +LL | type Assoc = bool; + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` error: aborting due to previous error diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr index 95e8ebdd180b0..e4bd39c8ba62c 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr @@ -1,15 +1,13 @@ error[E0271]: type mismatch resolving `::Ok == ()` --> $DIR/point-at-type-on-obligation-failure.rs:13:5 | -LL | type Ok; - | -- associated type defined here +LL | type Ok; + | -- associated type defined here ... -LL | / impl Bar for Foo { -LL | | type Ok = (); - | | ^^^^^^^^^^^^^ expected u32, found () -LL | | type Sibling = Foo2; -LL | | } - | |_- in this `impl` item +LL | impl Bar for Foo { + | ---------------- in this `impl` item +LL | type Ok = (); + | ^^^^^^^^^^^^^ expected u32, found () | = note: expected type `u32` found type `()` diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index cfab66302cdca..33692bd254e76 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -1,15 +1,15 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-43784-associated-type.rs:14:5 | -LL | type Assoc: Partial; - | ----- associated type defined here +LL | type Assoc: Partial; + | ----- associated type defined here ... -LL | / impl Complete for T { - | | - help: consider restricting this bound: `T: std::marker::Copy` -LL | | type Assoc = T; - | | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` -LL | | } - | |_- in this `impl` item +LL | impl Complete for T { + | ---------------------- in this `impl` item + | | + | help: consider restricting this bound: `T: std::marker::Copy` +LL | type Assoc = T; + | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | = help: consider adding a `where T: std::marker::Copy` bound diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index a7b8dd05527a5..f439de8826117 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -9,14 +9,13 @@ LL | _parse: >::Data, error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase` --> $DIR/cycle-cache-err-60010.rs:31:5 | -LL | type Storage; - | ------- associated type defined here +LL | type Storage; + | ------- associated type defined here ... -LL | / impl Database for RootDatabase { -LL | | type Storage = SalsaStorage; - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | | } - | |_- in this `impl` item +LL | impl Database for RootDatabase { + | ------------------------------ in this `impl` item +LL | type Storage = SalsaStorage; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: required because of the requirements on the impl of `Query` for `ParseQuery` = note: required because it appears within the type `SalsaStorage` From 580a93e2b6bd1817c81a248b469b01476f0ee328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Oct 2019 13:23:55 -0700 Subject: [PATCH 06/22] Fix rebase --- .../issues/issue-43784-associated-type.stderr | 9 ++++----- .../missing-assoc-type-bound-restriction.rs | 2 +- ...missing-assoc-type-bound-restriction.stderr | 18 ++++++++++++------ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index 33692bd254e76..393b012f5f8a7 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -5,13 +5,12 @@ LL | type Assoc: Partial; | ----- associated type defined here ... LL | impl Complete for T { - | ---------------------- in this `impl` item - | | - | help: consider restricting this bound: `T: std::marker::Copy` + | ---------------------- + | | | + | | help: consider restricting this bound: `T: std::marker::Copy` + | in this `impl` item LL | type Assoc = T; | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs index 265ccb3125ca3..394512c579474 100644 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs @@ -16,10 +16,10 @@ struct ParentWrapper(T); impl> Parent for ParentWrapper { //~^ ERROR the trait bound `::Assoc: Child` is not satisfied - //~| ERROR the trait bound `::Assoc: Child` is not satisfied type Ty = A; type Assoc = ChildWrapper; //~^ ERROR the trait bound `::Assoc: Child` is not satisfied + //~| ERROR the trait bound `::Assoc: Child` is not satisfied } fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr index bdea8ab97e5b5..c6f2e5cda66af 100644 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr @@ -9,25 +9,31 @@ LL | impl> Parent for ParentWrapper { | _| | | LL | | -LL | | LL | | type Ty = A; LL | | type Assoc = ChildWrapper; LL | | +LL | | LL | | } | |_^ the trait `Child` is not implemented for `::Assoc` error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:17:28 + --> $DIR/missing-assoc-type-bound-restriction.rs:20:5 | +LL | type Assoc: Child; + | ----- associated type defined here +... LL | impl> Parent for ParentWrapper { - | ^^^^^^ - help: consider further restricting the associated type: `where ::Assoc: Child` - | | - | the trait `Child` is not implemented for `::Assoc` + | ------------------------------------------------------- help: consider further restricting the associated type: `where ::Assoc: Child` + | | + | in this `impl` item +... +LL | type Assoc = ChildWrapper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` | = note: required because of the requirements on the impl of `Child` for `ChildWrapper<::Assoc>` error[E0277]: the trait bound `::Assoc: Child` is not satisfied - --> $DIR/missing-assoc-type-bound-restriction.rs:21:5 + --> $DIR/missing-assoc-type-bound-restriction.rs:20:5 | LL | trait Parent { | ------------ required by `Parent` From 3a4cacd45891db4a898606fc7b26d4b73009e5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Oct 2019 14:02:15 -0700 Subject: [PATCH 07/22] Add comments --- src/librustc/ty/wf.rs | 73 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 84bcec6bd199f..9f8e62a061422 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -179,6 +179,47 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span)); match pred { ty::Predicate::Projection(proj) => { + // The obligation comes not from the current `impl` nor the `trait` being + // implemented, but rather from a "second order" obligation, like in + // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`: + // + // error[E0271]: type mismatch resolving `::Ok == ()` + // --> $DIR/point-at-type-on-obligation-failure.rs:13:5 + // | + // LL | type Ok; + // | -- associated type defined here + // ... + // LL | impl Bar for Foo { + // | ---------------- in this `impl` item + // LL | type Ok = (); + // | ^^^^^^^^^^^^^ expected u32, found () + // | + // = note: expected type `u32` + // found type `()` + // + // FIXME: we would want to point a span to all places that contributed to this + // obligation. In the case above, it should be closer to: + // + // error[E0271]: type mismatch resolving `::Ok == ()` + // --> $DIR/point-at-type-on-obligation-failure.rs:13:5 + // | + // LL | type Ok; + // | -- associated type defined here + // LL | type Sibling: Bar2; + // | -------------------------------- obligation set here + // ... + // LL | impl Bar for Foo { + // | ---------------- in this `impl` item + // LL | type Ok = (); + // | ^^^^^^^^^^^^^ expected u32, found () + // ... + // LL | impl Bar2 for Foo2 { + // | ---------------- in this `impl` item + // LL | type Ok = u32; + // | -------------- obligation set here + // | + // = note: expected type `u32` + // found type `()` if let Some(hir::ItemKind::Impl(.., impl_items)) = item.map(|i| &i.kind) { let trait_assoc_item = tcx.associated_item(proj.projection_def_id()); if let Some(impl_item) = impl_items.iter().filter(|item| { @@ -193,6 +234,38 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } ty::Predicate::Trait(proj) => { + // An associated item obligation born out of the `trait` failed to be met. + // Point at the `impl` that failed the obligation, the associated item that + // needed to meet the obligation, and the definition of that associated item, + // which should hold the obligation in most cases. An example can be seen in + // `src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs`: + // + // error[E0277]: the trait bound `bool: Bar` is not satisfied + // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 + // | + // LL | type Assoc: Bar; + // | ----- associated type defined here + // ... + // LL | impl Foo for () { + // | --------------- in this `impl` item + // LL | type Assoc = bool; + // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` + // + // FIXME: if the obligation comes from the where clause in the `trait`, we + // should point at it: + // + // error[E0277]: the trait bound `bool: Bar` is not satisfied + // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 + // | + // | trait Foo where >::Assoc: Bar { + // | -------------------------- obligation set here + // LL | type Assoc; + // | ----- associated type defined here + // ... + // LL | impl Foo for () { + // | --------------- in this `impl` item + // LL | type Assoc = bool; + // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` if let ( ty::Projection(ty::ProjectionTy { item_def_id, .. }), Some(hir::ItemKind::Impl(.., impl_items)), From 93cac9c3da06e1fbbdee10df7525234ffc7c76cd Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Oct 2019 04:24:22 +0300 Subject: [PATCH 08/22] rustc: add `Span`s to `inferred_outlives_of` predicates. --- src/librustc/query/mod.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc_lint/builtin.rs | 10 ++++----- src/librustc_typeck/collect.rs | 15 ++++++------- src/librustc_typeck/outlives/mod.rs | 33 ++++++++++++++++++++++------- 5 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index fdca6d0e17a1d..7cae74b59c7f9 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -191,7 +191,7 @@ rustc_queries! { /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). - query inferred_outlives_of(_: DefId) -> &'tcx [ty::Predicate<'tcx>] {} + query inferred_outlives_of(_: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {} /// Maps from the `DefId` of a trait to the list of /// super-predicates. This is a subset of the full list of diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index feede00fea1c3..e58ba9d6a2b3a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1136,7 +1136,7 @@ pub struct CratePredicatesMap<'tcx> { /// For each struct with outlive bounds, maps to a vector of the /// predicate of its outlive bounds. If an item has no outlives /// bounds, it will have no entry. - pub predicates: FxHashMap]>, + pub predicates: FxHashMap, Span)]>, } impl<'tcx> AsRef> for Predicate<'tcx> { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ad674911e6f33..7c19449f96b86 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1497,10 +1497,10 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN impl ExplicitOutlivesRequirements { fn lifetimes_outliving_lifetime<'tcx>( - inferred_outlives: &'tcx [ty::Predicate<'tcx>], + inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], index: u32, ) -> Vec> { - inferred_outlives.iter().filter_map(|pred| { + inferred_outlives.iter().filter_map(|(pred, _)| { match pred { ty::Predicate::RegionOutlives(outlives) => { let outlives = outlives.skip_binder(); @@ -1517,10 +1517,10 @@ impl ExplicitOutlivesRequirements { } fn lifetimes_outliving_type<'tcx>( - inferred_outlives: &'tcx [ty::Predicate<'tcx>], + inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], index: u32, ) -> Vec> { - inferred_outlives.iter().filter_map(|pred| { + inferred_outlives.iter().filter_map(|(pred, _)| { match pred { ty::Predicate::TypeOutlives(outlives) => { let outlives = outlives.skip_binder(); @@ -1539,7 +1539,7 @@ impl ExplicitOutlivesRequirements { &self, param: &'tcx hir::GenericParam, tcx: TyCtxt<'tcx>, - inferred_outlives: &'tcx [ty::Predicate<'tcx>], + inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], ty_generics: &'tcx ty::Generics, ) -> Vec> { let index = ty_generics.param_def_id_to_index[ diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d4c64512f984b..78347ded72635 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1970,19 +1970,18 @@ fn predicates_defined_on( ); let inferred_outlives = tcx.inferred_outlives_of(def_id); if !inferred_outlives.is_empty() { - let span = tcx.def_span(def_id); debug!( "predicates_defined_on: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives, ); - result.predicates = tcx.arena.alloc_from_iter( - result.predicates.iter().copied().chain( - // FIXME(eddyb) use better spans - maybe add `Span`s - // to `inferred_outlives_of` predicates as well? - inferred_outlives.iter().map(|&p| (p, span)), - ), - ); + if result.predicates.is_empty() { + result.predicates = inferred_outlives; + } else { + result.predicates = tcx.arena.alloc_from_iter( + result.predicates.iter().chain(inferred_outlives).copied(), + ); + } } debug!("predicates_defined_on({:?}) = {:?}", def_id, result); result diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index cdb83eb328ac2..b2699fffc2c17 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -5,6 +5,7 @@ use rustc::ty::query::Providers; use rustc::ty::subst::GenericArgKind; use rustc::ty::{self, CratePredicatesMap, TyCtxt}; use syntax::symbol::sym; +use syntax_pos::Span; mod explicit; mod implicit_infer; @@ -23,7 +24,7 @@ pub fn provide(providers: &mut Providers<'_>) { fn inferred_outlives_of( tcx: TyCtxt<'_>, item_def_id: DefId, -) -> &[ty::Predicate<'_>] { +) -> &[(ty::Predicate<'_>, Span)] { let id = tcx .hir() .as_local_hir_id(item_def_id) @@ -43,7 +44,7 @@ fn inferred_outlives_of( if tcx.has_attr(item_def_id, sym::rustc_outlives) { let mut pred: Vec = predicates .iter() - .map(|out_pred| match out_pred { + .map(|(out_pred, _)| match out_pred { ty::Predicate::RegionOutlives(p) => p.to_string(), ty::Predicate::TypeOutlives(p) => p.to_string(), err => bug!("unexpected predicate {:?}", err), @@ -96,19 +97,35 @@ fn inferred_outlives_crate( let predicates = global_inferred_outlives .iter() .map(|(&def_id, set)| { - let predicates = tcx.arena.alloc_from_iter(set + let def_span = tcx.def_span(def_id); + let generics = tcx.generics_of(def_id); + let predicates = &*tcx.arena.alloc_from_iter(set .iter() .filter_map( |ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() { GenericArgKind::Type(ty1) => { - Some(ty::Predicate::TypeOutlives(ty::Binder::bind( + // FIXME(eddyb) compute `Span`s in `implicit_infer`. + let span = match &ty1.kind { + ty::Param(p) => { + tcx.def_span(generics.type_param(p, tcx).def_id) + } + _ => def_span, + }; + Some((ty::Predicate::TypeOutlives(ty::Binder::bind( ty::OutlivesPredicate(ty1, region2) - ))) + )), span)) } GenericArgKind::Lifetime(region1) => { - Some(ty::Predicate::RegionOutlives( + // FIXME(eddyb) compute `Span`s in `implicit_infer`. + let span = match region1 { + ty::RegionKind::ReEarlyBound(p) => { + tcx.def_span(generics.region_param(p, tcx).def_id) + } + _ => def_span, + }; + Some((ty::Predicate::RegionOutlives( ty::Binder::bind(ty::OutlivesPredicate(region1, region2)) - )) + ), span)) } GenericArgKind::Const(_) => { // Generic consts don't impose any constraints. @@ -116,7 +133,7 @@ fn inferred_outlives_crate( } }, )); - (def_id, &*predicates) + (def_id, predicates) }).collect(); tcx.arena.alloc(ty::CratePredicatesMap { From 1ca8da40366a417aef90415d8f745764cab5783b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 19 Oct 2019 03:45:16 +0300 Subject: [PATCH 09/22] rustc_typeck: compute better spans for inferred_outlives. --- src/librustc_metadata/encoder.rs | 8 ++++++++ src/librustc_typeck/outlives/explicit.rs | 13 ++++++++++--- src/librustc_typeck/outlives/implicit_infer.rs | 13 +++++++++---- src/librustc_typeck/outlives/mod.rs | 18 +----------------- src/librustc_typeck/outlives/utils.rs | 16 +++++++++++----- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0dc9f91ae00e1..08554c83ed5bf 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -197,6 +197,13 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { return TAG_INVALID_SPAN.encode(self) } + // HACK(eddyb) there's no way to indicate which crate a Span is coming + // from right now, so decoding would fail to find the SourceFile if + // it's not local to the crate the Span is found in. + if self.source_file_cache.is_imported() { + return TAG_INVALID_SPAN.encode(self) + } + TAG_VALID_SPAN.encode(self)?; span.lo.encode(self)?; @@ -379,6 +386,7 @@ impl<'tcx> EncodeContext<'tcx> { .filter(|source_file| { // No need to re-export imported source_files, as any downstream // crate will import them from their original source. + // FIXME(eddyb) the `Span` encoding should take that into account. !source_file.is_imported() }) .map(|source_file| { diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs index 83194144216ee..21e529f33cfd0 100644 --- a/src/librustc_typeck/outlives/explicit.rs +++ b/src/librustc_typeck/outlives/explicit.rs @@ -30,11 +30,17 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { let mut required_predicates = RequiredPredicates::default(); // process predicates and convert to `RequiredPredicates` entry, see below - for (pred, _) in predicates.predicates { - match pred { + for &(predicate, span) in predicates.predicates { + match predicate { ty::Predicate::TypeOutlives(predicate) => { let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder(); - insert_outlives_predicate(tcx, (*ty).into(), reg, &mut required_predicates) + insert_outlives_predicate( + tcx, + (*ty).into(), + reg, + span, + &mut required_predicates, + ) } ty::Predicate::RegionOutlives(predicate) => { @@ -43,6 +49,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { tcx, (*reg1).into(), reg2, + span, &mut required_predicates, ) } diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 433d04ffa64ff..74048b8d20c82 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -4,6 +4,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::subst::{GenericArg, Subst, GenericArgKind}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; +use syntax_pos::Span; use super::explicit::ExplicitPredicatesMap; use super::utils::*; @@ -79,9 +80,11 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> { // (struct/enum/union) there will be outlive // requirements for adt_def. let field_ty = self.tcx.type_of(field_def.did); + let field_span = self.tcx.def_span(field_def.did); insert_required_predicates_to_be_wf( self.tcx, field_ty, + field_span, self.global_inferred_outlives, &mut item_required_predicates, &mut self.explicit_map, @@ -118,6 +121,7 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> { fn insert_required_predicates_to_be_wf<'tcx>( tcx: TyCtxt<'tcx>, field_ty: Ty<'tcx>, + field_span: Span, global_inferred_outlives: &FxHashMap>, required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, @@ -130,7 +134,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( // We also want to calculate potential predicates for the T ty::Ref(region, rty, _) => { debug!("Ref"); - insert_outlives_predicate(tcx, rty.into(), region, required_predicates); + insert_outlives_predicate(tcx, rty.into(), region, field_span, required_predicates); } // For each Adt (struct/enum/union) type `Foo<'a, T>`, we @@ -158,7 +162,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( // 'a` holds for `Foo`. debug!("Adt"); if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) { - for unsubstituted_predicate in unsubstituted_predicates { + for (unsubstituted_predicate, &span) in unsubstituted_predicates { // `unsubstituted_predicate` is `U: 'b` in the // example above. So apply the substitution to // get `T: 'a` (or `predicate`): @@ -167,6 +171,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( tcx, predicate.0, predicate.1, + span, required_predicates, ); } @@ -272,7 +277,7 @@ pub fn check_explicit_predicates<'tcx>( ); let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id); - for outlives_predicate in explicit_predicates.iter() { + for (outlives_predicate, &span) in explicit_predicates { debug!("outlives_predicate = {:?}", &outlives_predicate); // Careful: If we are inferring the effects of a `dyn Trait<..>` @@ -320,6 +325,6 @@ pub fn check_explicit_predicates<'tcx>( let predicate = outlives_predicate.subst(tcx, substs); debug!("predicate = {:?}", &predicate); - insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, required_predicates); + insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, span, required_predicates); } } diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index b2699fffc2c17..6b861656d7e2d 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -97,32 +97,16 @@ fn inferred_outlives_crate( let predicates = global_inferred_outlives .iter() .map(|(&def_id, set)| { - let def_span = tcx.def_span(def_id); - let generics = tcx.generics_of(def_id); let predicates = &*tcx.arena.alloc_from_iter(set .iter() .filter_map( - |ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() { + |(ty::OutlivesPredicate(kind1, region2), &span)| match kind1.unpack() { GenericArgKind::Type(ty1) => { - // FIXME(eddyb) compute `Span`s in `implicit_infer`. - let span = match &ty1.kind { - ty::Param(p) => { - tcx.def_span(generics.type_param(p, tcx).def_id) - } - _ => def_span, - }; Some((ty::Predicate::TypeOutlives(ty::Binder::bind( ty::OutlivesPredicate(ty1, region2) )), span)) } GenericArgKind::Lifetime(region1) => { - // FIXME(eddyb) compute `Span`s in `implicit_infer`. - let span = match region1 { - ty::RegionKind::ReEarlyBound(p) => { - tcx.def_span(generics.region_param(p, tcx).def_id) - } - _ => def_span, - }; Some((ty::Predicate::RegionOutlives( ty::Binder::bind(ty::OutlivesPredicate(region1, region2)) ), span)) diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index d34605dc482a3..361116e96d0bf 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -2,12 +2,13 @@ use rustc::ty::outlives::Component; use rustc::ty::subst::{GenericArg, GenericArgKind}; use rustc::ty::{self, Region, RegionKind, Ty, TyCtxt}; use smallvec::smallvec; -use std::collections::BTreeSet; +use std::collections::BTreeMap; +use syntax_pos::Span; /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred /// must be added to the struct header. pub type RequiredPredicates<'tcx> = - BTreeSet, ty::Region<'tcx>>>; + BTreeMap, ty::Region<'tcx>>, Span>; /// Given a requirement `T: 'a` or `'b: 'a`, deduce the /// outlives_component and add it to `required_predicates` @@ -15,6 +16,7 @@ pub fn insert_outlives_predicate<'tcx>( tcx: TyCtxt<'tcx>, kind: GenericArg<'tcx>, outlived_region: Region<'tcx>, + span: Span, required_predicates: &mut RequiredPredicates<'tcx>, ) { // If the `'a` region is bound within the field type itself, we @@ -53,6 +55,7 @@ pub fn insert_outlives_predicate<'tcx>( tcx, r.into(), outlived_region, + span, required_predicates, ); } @@ -73,7 +76,8 @@ pub fn insert_outlives_predicate<'tcx>( // where clause that `U: 'a`. let ty: Ty<'tcx> = param_ty.to_ty(tcx); required_predicates - .insert(ty::OutlivesPredicate(ty.into(), outlived_region)); + .entry(ty::OutlivesPredicate(ty.into(), outlived_region)) + .or_insert(span); } Component::Projection(proj_ty) => { @@ -88,7 +92,8 @@ pub fn insert_outlives_predicate<'tcx>( // Here we want to add an explicit `where ::Item: 'a`. let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs); required_predicates - .insert(ty::OutlivesPredicate(ty.into(), outlived_region)); + .entry(ty::OutlivesPredicate(ty.into(), outlived_region)) + .or_insert(span); } Component::EscapingProjection(_) => { @@ -117,7 +122,8 @@ pub fn insert_outlives_predicate<'tcx>( if !is_free_region(tcx, r) { return; } - required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region)); + required_predicates.entry(ty::OutlivesPredicate(kind, outlived_region)) + .or_insert(span); } GenericArgKind::Const(_) => { From 707315857a506f99d123a98670341b2d619bca9c Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 20 Oct 2019 22:08:26 +0100 Subject: [PATCH 10/22] Don't ICE for completely unexpandable `impl Trait` types --- src/librustc_typeck/check/writeback.rs | 10 +++-- .../recursive-impl-trait-type-direct.rs | 7 ++++ .../recursive-impl-trait-type-direct.stderr | 11 +++++ ... => recursive-impl-trait-type-indirect.rs} | 0 ...recursive-impl-trait-type-indirect.stderr} | 40 +++++++++---------- ...-impl-trait-type-through-non-recursive.rs} | 0 ...l-trait-type-through-non-recursive.stderr} | 8 ++-- 7 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr rename src/test/ui/impl-trait/{recursive-impl-trait-type.rs => recursive-impl-trait-type-indirect.rs} (100%) rename src/test/ui/impl-trait/{recursive-impl-trait-type.stderr => recursive-impl-trait-type-indirect.stderr} (76%) rename src/test/ui/impl-trait/{recursive-impl-trait-type--through-non-recursize.rs => recursive-impl-trait-type-through-non-recursive.rs} (100%) rename src/test/ui/impl-trait/{recursive-impl-trait-type--through-non-recursize.stderr => recursive-impl-trait-type-through-non-recursive.stderr} (77%) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 7a8a209a5350c..3d380a5f1826c 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -479,10 +479,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let mut skip_add = false; if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.kind { - if def_id == defin_ty_def_id { - debug!("Skipping adding concrete definition for opaque type {:?} {:?}", - opaque_defn, defin_ty_def_id); - skip_add = true; + if let hir::OpaqueTyOrigin::TypeAlias = opaque_defn.origin { + if def_id == defin_ty_def_id { + debug!("Skipping adding concrete definition for opaque type {:?} {:?}", + opaque_defn, defin_ty_def_id); + skip_add = true; + } } } diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs new file mode 100644 index 0000000000000..b22d216553389 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs @@ -0,0 +1,7 @@ +// Test that an impl trait type that expands to itself is an error. + +fn test() -> impl Sized { //~ ERROR E0720 + test() +} + +fn main() {} diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr new file mode 100644 index 0000000000000..1b5dbd814a481 --- /dev/null +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr @@ -0,0 +1,11 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/recursive-impl-trait-type-direct.rs:3:14 + | +LL | fn test() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs similarity index 100% rename from src/test/ui/impl-trait/recursive-impl-trait-type.rs rename to src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr similarity index 76% rename from src/test/ui/impl-trait/recursive-impl-trait-type.stderr rename to src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr index 324607117dc50..b7ba0d6ab177c 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr @@ -1,5 +1,5 @@ error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:6:22 + --> $DIR/recursive-impl-trait-type-indirect.rs:6:22 | LL | fn option(i: i32) -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -7,7 +7,7 @@ LL | fn option(i: i32) -> impl Sized { = note: expanded type is `std::option::Option<(impl Sized, i32)>` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:14:15 + --> $DIR/recursive-impl-trait-type-indirect.rs:14:15 | LL | fn tuple() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -15,7 +15,7 @@ LL | fn tuple() -> impl Sized { = note: expanded type is `(impl Sized,)` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:18:15 + --> $DIR/recursive-impl-trait-type-indirect.rs:18:15 | LL | fn array() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -23,7 +23,7 @@ LL | fn array() -> impl Sized { = note: expanded type is `[impl Sized; 1]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:22:13 + --> $DIR/recursive-impl-trait-type-indirect.rs:22:13 | LL | fn ptr() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -31,7 +31,7 @@ LL | fn ptr() -> impl Sized { = note: expanded type is `*const impl Sized` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:26:16 + --> $DIR/recursive-impl-trait-type-indirect.rs:26:16 | LL | fn fn_ptr() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -39,47 +39,47 @@ LL | fn fn_ptr() -> impl Sized { = note: expanded type is `fn() -> impl Sized` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:30:25 + --> $DIR/recursive-impl-trait-type-indirect.rs:30:25 | LL | fn closure_capture() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:32:5: 32:19 x:impl Sized]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:32:5: 32:19 x:impl Sized]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:35:29 + --> $DIR/recursive-impl-trait-type-indirect.rs:35:29 | LL | fn closure_ref_capture() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:37:5: 37:20 x:impl Sized]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:37:5: 37:20 x:impl Sized]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:40:21 + --> $DIR/recursive-impl-trait-type-indirect.rs:40:21 | LL | fn closure_sig() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:41:5: 41:21]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:41:5: 41:21]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:44:23 + --> $DIR/recursive-impl-trait-type-indirect.rs:44:23 | LL | fn generator_sig() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type.rs:45:5: 45:23]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:45:5: 45:23]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:48:27 + --> $DIR/recursive-impl-trait-type-indirect.rs:48:27 | LL | fn generator_capture() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:50:5: 50:26 x:impl Sized {()}]` + = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {()}]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:53:26 + --> $DIR/recursive-impl-trait-type-indirect.rs:53:26 | LL | fn substs_change() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -87,15 +87,15 @@ LL | fn substs_change() -> impl Sized { = note: expanded type is `(impl Sized,)` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:57:24 + --> $DIR/recursive-impl-trait-type-indirect.rs:57:24 | LL | fn generator_hold() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]` + = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, ()}]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:69:26 + --> $DIR/recursive-impl-trait-type-indirect.rs:69:26 | LL | fn mutual_recursion() -> impl Sync { | ^^^^^^^^^ expands to a recursive type @@ -103,7 +103,7 @@ LL | fn mutual_recursion() -> impl Sync { = note: type resolves to itself error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type.rs:73:28 + --> $DIR/recursive-impl-trait-type-indirect.rs:73:28 | LL | fn mutual_recursion_b() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs similarity index 100% rename from src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs rename to src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr similarity index 77% rename from src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr rename to src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr index 7572c6c1bf057..73c12f6137d24 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr @@ -1,5 +1,5 @@ error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:7:22 + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:7:22 | LL | fn recursive_id() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -7,7 +7,7 @@ LL | fn recursive_id() -> impl Sized { = note: type resolves to itself error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:11:23 + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:11:23 | LL | fn recursive_id2() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -15,7 +15,7 @@ LL | fn recursive_id2() -> impl Sized { = note: type resolves to itself error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:17:24 + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:17:24 | LL | fn recursive_wrap() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -23,7 +23,7 @@ LL | fn recursive_wrap() -> impl Sized { = note: expanded type is `((impl Sized,),)` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:21:25 + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:21:25 | LL | fn recursive_wrap2() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type From 949874ac2db76082eedbd4ae53e927ea5b053863 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 25 Oct 2019 08:06:01 -0400 Subject: [PATCH 11/22] Remove unused get_any method --- src/librustc/lint/mod.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 3c35bdae66e9d..dbdd8afa79869 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -646,11 +646,6 @@ impl LintBuffer { pub fn take(&mut self, id: ast::NodeId) -> Vec { self.map.remove(&id).unwrap_or_default() } - - pub fn get_any(&self) -> Option<&[BufferedEarlyLint]> { - let key = self.map.keys().next().map(|k| *k); - key.map(|k| &self.map[&k][..]) - } } pub fn struct_lint_level<'a>(sess: &'a Session, From fa637fac523ffaa01d8cf71ef59748373fe2aece Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 25 Oct 2019 08:08:53 -0400 Subject: [PATCH 12/22] Only permit taking buffered lints inside lint internals --- src/librustc/lint/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index dbdd8afa79869..8b5ef89a73166 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -643,7 +643,7 @@ impl LintBuffer { } } - pub fn take(&mut self, id: ast::NodeId) -> Vec { + fn take(&mut self, id: ast::NodeId) -> Vec { self.map.remove(&id).unwrap_or_default() } } From 103329889dc1048ebb4680a8ac66168cf85945ed Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 25 Oct 2019 09:15:33 -0400 Subject: [PATCH 13/22] Migrate resolver over to internal lint buffer --- src/librustc/lint/mod.rs | 21 +++++++++++++++++++++ src/librustc/middle/stability.rs | 4 ++-- src/librustc_interface/passes.rs | 8 +++++--- src/librustc_passes/ast_validation.rs | 21 ++++++++++++--------- src/librustc_resolve/check_unused.rs | 6 +++--- src/librustc_resolve/late.rs | 6 +++--- src/librustc_resolve/lib.rs | 16 ++++++++++------ src/librustc_resolve/macros.rs | 16 +++++++++------- src/librustc_resolve/resolve_imports.rs | 6 +++--- src/libsyntax_expand/base.rs | 4 ++-- 10 files changed, 70 insertions(+), 38 deletions(-) diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 8b5ef89a73166..9fdb09023290c 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -646,6 +646,27 @@ impl LintBuffer { fn take(&mut self, id: ast::NodeId) -> Vec { self.map.remove(&id).unwrap_or_default() } + + pub fn buffer_lint>( + &mut self, + lint: &'static Lint, + id: ast::NodeId, + sp: S, + msg: &str, + ) { + self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal) + } + + pub fn buffer_lint_with_diagnostic>( + &mut self, + lint: &'static Lint, + id: ast::NodeId, + sp: S, + msg: &str, + diagnostic: BuiltinLintDiagnostics, + ) { + self.add_lint(lint, id, sp.into(), msg, diagnostic) + } } pub fn struct_lint_level<'a>(sess: &'a Session, diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e65f17c79497e..93d0627ac6e40 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -586,7 +586,7 @@ pub fn rustc_deprecation_message(depr: &RustcDeprecation, path: &str) -> (String } pub fn early_report_deprecation( - sess: &Session, + lint_buffer: &'a mut lint::LintBuffer, message: &str, suggestion: Option, lint: &'static Lint, @@ -597,7 +597,7 @@ pub fn early_report_deprecation( } let diag = BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span); - sess.buffer_lint_with_diagnostic(lint, CRATE_NODE_ID, span, message, diag); + lint_buffer.buffer_lint_with_diagnostic(lint, CRATE_NODE_ID, span, message, diag); } fn late_report_deprecation( diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 58936172c5bce..6e37c0302f310 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -270,12 +270,14 @@ fn configure_and_expand_inner<'a>( rustc_lint::BuiltinCombinedPreExpansionLintPass::new()); }); + let lint_buffer = lint::LintBuffer::default(); let mut resolver = Resolver::new( sess, &krate, crate_name, metadata_loader, &resolver_arenas, + lint_buffer, ); syntax_ext::register_builtin_macros(&mut resolver, sess.edition()); @@ -366,7 +368,7 @@ fn configure_and_expand_inner<'a>( for span in missing_fragment_specifiers { let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; let msg = "missing fragment specifier"; - sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg); + resolver.lint_buffer.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg); } if cfg!(windows) { env::set_var("PATH", &old_path); @@ -395,7 +397,7 @@ fn configure_and_expand_inner<'a>( } let has_proc_macro_decls = time(sess, "AST validation", || { - ast_validation::check_crate(sess, &krate) + ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer) }); @@ -464,7 +466,7 @@ fn configure_and_expand_inner<'a>( info!("{} parse sess buffered_lints", buffered_lints.len()); for BufferedEarlyLint{id, span, msg, lint_id} in buffered_lints.drain(..) { let lint = lint::Lint::from_parser_lint_id(lint_id); - sess.buffer_lint(lint, id, span, &msg); + resolver.lint_buffer.buffer_lint(lint, id, span, &msg); } }); diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 74de31263d394..978ea20aa3397 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -73,6 +73,8 @@ struct AstValidator<'a> { /// these booleans. warning_period_57979_didnt_record_next_impl_trait: bool, warning_period_57979_impl_trait_in_proj: bool, + + lint_buffer: &'a mut lint::LintBuffer, } impl<'a> AstValidator<'a> { @@ -229,7 +231,7 @@ impl<'a> AstValidator<'a> { err.emit(); } - fn check_decl_no_pat(&self, decl: &FnDecl, report_err: ReportFn) { + fn check_decl_no_pat(decl: &FnDecl, mut report_err: F) { for arg in &decl.inputs { match arg.pat.kind { PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) | @@ -460,7 +462,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match ty.kind { TyKind::BareFn(ref bfty) => { self.check_fn_decl(&bfty.decl); - self.check_decl_no_pat(&bfty.decl, |span, _| { + Self::check_decl_no_pat(&bfty.decl, |span, _| { struct_span_err!(self.session, span, E0561, "patterns aren't allowed in function pointer types").emit(); }); @@ -483,7 +485,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { TyKind::ImplTrait(_, ref bounds) => { if self.is_impl_trait_banned { if self.warning_period_57979_impl_trait_in_proj { - self.session.buffer_lint( + self.lint_buffer.buffer_lint( NESTED_IMPL_TRAIT, ty.id, ty.span, "`impl Trait` is not allowed in path parameters"); } else { @@ -494,7 +496,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let Some(outer_impl_trait) = self.outer_impl_trait { if outer_impl_trait.should_warn_instead_of_error() { - self.session.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint_with_diagnostic( NESTED_IMPL_TRAIT, ty.id, ty.span, "nested `impl Trait` is not allowed", BuiltinLintDiagnostics::NestedImplTrait { @@ -634,9 +636,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node); self.check_trait_fn_not_const(sig.header.constness); if block.is_none() { - self.check_decl_no_pat(&sig.decl, |span, mut_ident| { + Self::check_decl_no_pat(&sig.decl, |span, mut_ident| { if mut_ident { - self.session.buffer_lint( + self.lint_buffer.buffer_lint( lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, trait_item.id, span, "patterns aren't allowed in methods without bodies"); @@ -655,7 +657,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if attr::contains_name(&item.attrs, sym::warn_directory_ownership) { let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP; let msg = "cannot declare a new module at this location"; - self.session.buffer_lint(lint, item.id, item.span, msg); + self.lint_buffer.buffer_lint(lint, item.id, item.span, msg); } } ItemKind::Union(ref vdata, _) => { @@ -686,7 +688,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match fi.kind { ForeignItemKind::Fn(ref decl, _) => { self.check_fn_decl(decl); - self.check_decl_no_pat(decl, |span, _| { + Self::check_decl_no_pat(decl, |span, _| { struct_span_err!(self.session, span, E0130, "patterns aren't allowed in foreign function declarations") .span_label(span, "pattern not allowed in foreign function").emit(); @@ -840,7 +842,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } -pub fn check_crate(session: &Session, krate: &Crate) -> bool { +pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool { let mut validator = AstValidator { session, has_proc_macro_decls: false, @@ -849,6 +851,7 @@ pub fn check_crate(session: &Session, krate: &Crate) -> bool { is_assoc_ty_bound_banned: false, warning_period_57979_didnt_record_next_impl_trait: false, warning_period_57979_impl_trait_in_proj: false, + lint_buffer: lints, }; visit::walk_crate(&mut validator, krate); diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 737589acf8d81..44b7a9fa047c2 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -232,7 +232,7 @@ impl Resolver<'_> { directive.span.is_dummy() => { if let ImportDirectiveSubclass::MacroUse = directive.subclass { if !directive.span.is_dummy() { - self.session.buffer_lint( + self.lint_buffer.buffer_lint( lint::builtin::MACRO_USE_EXTERN_CRATE, directive.id, directive.span, @@ -250,7 +250,7 @@ impl Resolver<'_> { ImportDirectiveSubclass::MacroUse => { let lint = lint::builtin::UNUSED_IMPORTS; let msg = "unused `#[macro_use]` import"; - self.session.buffer_lint(lint, directive.id, directive.span, msg); + self.lint_buffer.buffer_lint(lint, directive.id, directive.span, msg); } _ => {} } @@ -312,7 +312,7 @@ impl Resolver<'_> { "remove the unused import" }; - visitor.r.session.buffer_lint_with_diagnostic( + visitor.r.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::UNUSED_IMPORTS, unused.use_tree_id, ms, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 136ab1f0444fa..0d4e805045294 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1511,7 +1511,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { if is_expected(ctor_res) && self.r.is_accessible_from(ctor_vis, self.parent_scope.module) { let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY; - self.r.session.buffer_lint(lint, id, span, + self.r.lint_buffer.buffer_lint(lint, id, span, "private struct constructors are not usable through \ re-exports in outer modules", ); @@ -1737,7 +1737,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { }; if result.base_res() == unqualified_result { let lint = lint::builtin::UNUSED_QUALIFICATIONS; - self.r.session.buffer_lint(lint, id, span, "unnecessary qualification") + self.r.lint_buffer.buffer_lint(lint, id, span, "unnecessary qualification") } } @@ -2074,7 +2074,7 @@ impl<'a> Resolver<'a> { let mut late_resolution_visitor = LateResolutionVisitor::new(self); visit::walk_crate(&mut late_resolution_visitor, krate); for (id, span) in late_resolution_visitor.unused_labels.iter() { - self.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); + self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 9239280634724..110cc17ea1f44 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -961,6 +961,8 @@ pub struct Resolver<'a> { /// Stores enum visibilities to properly build a reduced graph /// when visiting the correspondent variants. variant_vis: DefIdMap, + + pub lint_buffer: lint::LintBuffer, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1087,7 +1089,8 @@ impl<'a> Resolver<'a> { krate: &Crate, crate_name: &str, metadata_loader: &'a MetadataLoaderDyn, - arenas: &'a ResolverArenas<'a>) + arenas: &'a ResolverArenas<'a>, + lint_buffer: lint::LintBuffer) -> Resolver<'a> { let root_def_id = DefId::local(CRATE_DEF_INDEX); let root_module_kind = ModuleKind::Def( @@ -1226,7 +1229,8 @@ impl<'a> Resolver<'a> { features.declared_lib_features.iter().map(|(feat, ..)| *feat) .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat)) .collect(), - variant_vis: Default::default() + variant_vis: Default::default(), + lint_buffer, } } @@ -1652,7 +1656,7 @@ impl<'a> Resolver<'a> { match result { Ok(binding) => { if let Some(node_id) = poisoned { - self.session.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, node_id, ident.span, &format!("cannot find {} `{}` in this scope", ns.descr(), ident), @@ -2117,7 +2121,7 @@ impl<'a> Resolver<'a> { } fn lint_if_path_starts_with_module( - &self, + &mut self, crate_lint: CrateLint, path: &[Segment], path_span: Span, @@ -2168,7 +2172,7 @@ impl<'a> Resolver<'a> { let diag = lint::builtin::BuiltinLintDiagnostics ::AbsPathWithModule(diag_span); - self.session.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, diag_id, diag_span, "absolute paths must start with `self`, `super`, \ @@ -2418,7 +2422,7 @@ impl<'a> Resolver<'a> { for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { let msg = "macro-expanded `macro_export` macros from the current crate \ cannot be referred to by absolute paths"; - self.session.buffer_lint_with_diagnostic( + self.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, CRATE_NODE_ID, span_use, msg, lint::builtin::BuiltinLintDiagnostics:: diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 94fe0cc57403e..98a1a7d5fa619 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -246,9 +246,9 @@ impl<'a> base::Resolver for Resolver<'a> { Ok(InvocationRes::Single(ext)) } - fn check_unused_macros(&self) { + fn check_unused_macros(&mut self) { for (&node_id, &span) in self.unused_macros.iter() { - self.session.buffer_lint( + self.lint_buffer.buffer_lint( lint::builtin::UNUSED_MACROS, node_id, span, "unused macro definition" ); } @@ -788,15 +788,17 @@ impl<'a> Resolver<'a> { } } - fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) { + fn check_stability_and_deprecation(&mut self, ext: &SyntaxExtension, path: &ast::Path) { let span = path.span; if let Some(stability) = &ext.stability { if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level { let feature = stability.feature; if !self.active_features.contains(&feature) && !span.allows_unstable(feature) { let node_id = ast::CRATE_NODE_ID; - let soft_handler = - |lint, span, msg: &_| self.session.buffer_lint(lint, node_id, span, msg); + let lint_buffer = &mut self.lint_buffer; + let soft_handler = |lint, span, msg: &_| { + lint_buffer.buffer_lint(lint, node_id, span, msg) + }; stability::report_unstable( self.session, feature, reason, issue, is_soft, span, soft_handler ); @@ -806,14 +808,14 @@ impl<'a> Resolver<'a> { let path = pprust::path_to_string(path); let (message, lint) = stability::rustc_deprecation_message(depr, &path); stability::early_report_deprecation( - self.session, &message, depr.suggestion, lint, span + &mut self.lint_buffer, &message, depr.suggestion, lint, span ); } } if let Some(depr) = &ext.deprecation { let path = pprust::path_to_string(&path); let (message, lint) = stability::deprecation_message(depr, &path); - stability::early_report_deprecation(self.session, &message, None, lint, span); + stability::early_report_deprecation(&mut self.lint_buffer, &message, None, lint, span); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 31340ddd68372..23648bc09d278 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -496,7 +496,7 @@ impl<'a> Resolver<'a> { if let (&NameBindingKind::Res(_, true), &NameBindingKind::Res(_, true)) = (&old_binding.kind, &binding.kind) { - this.session.buffer_lint_with_diagnostic( + this.lint_buffer.buffer_lint_with_diagnostic( DUPLICATE_MACRO_EXPORTS, CRATE_NODE_ID, binding.span, @@ -1147,7 +1147,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { re-exported (error E0365), consider declaring with \ `pub`", ident); - self.r.session.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE, + self.r.lint_buffer.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE, directive.id, directive.span, &msg); @@ -1272,7 +1272,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut redundant_spans: Vec<_> = redundant_span.present_items().collect(); redundant_spans.sort(); redundant_spans.dedup(); - self.r.session.buffer_lint_with_diagnostic( + self.r.lint_buffer.buffer_lint_with_diagnostic( UNUSED_IMPORTS, directive.id, directive.span, diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax_expand/base.rs index 58edf23a5b1e2..95a7a42824406 100644 --- a/src/libsyntax_expand/base.rs +++ b/src/libsyntax_expand/base.rs @@ -868,7 +868,7 @@ pub trait Resolver { &mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool ) -> Result; - fn check_unused_macros(&self); + fn check_unused_macros(&mut self); fn has_derives(&self, expn_id: ExpnId, derives: SpecialDerives) -> bool; fn add_derives(&mut self, expn_id: ExpnId, derives: SpecialDerives); @@ -1063,7 +1063,7 @@ impl<'a> ExtCtxt<'a> { Symbol::intern(st) } - pub fn check_unused_macros(&self) { + pub fn check_unused_macros(&mut self) { self.resolver.check_unused_macros(); } From cb440f03f20b90bd16579793a6a8d17843d4dea3 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 25 Oct 2019 09:20:18 -0400 Subject: [PATCH 14/22] Utilize Resolver lint buffer during HIR lowering --- src/librustc/hir/lowering.rs | 11 +++++++---- src/librustc/session/mod.rs | 10 ++++++---- src/librustc_interface/util.rs | 4 ++-- src/librustc_resolve/lib.rs | 4 ++++ 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 002e6874466bb..8dec12db9ca2b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -43,6 +43,7 @@ use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS}; use crate::hir::{GenericArg, ConstArg}; use crate::hir::ptr::P; +use crate::lint; use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, ELIDED_LIFETIMES_IN_PATHS}; use crate::middle::cstore::CrateStore; @@ -184,6 +185,8 @@ pub trait Resolver { ) -> (ast::Path, Res); fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; + + fn lint_buffer(&mut self) -> &mut lint::LintBuffer; } type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream; @@ -1857,7 +1860,7 @@ impl<'a> LoweringContext<'a> { GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), ParenthesizedGenericArgs::Warn => { - self.sess.buffer_lint( + self.resolver.lint_buffer().buffer_lint( PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, CRATE_NODE_ID, data.span, @@ -1953,7 +1956,7 @@ impl<'a> LoweringContext<'a> { } AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => { - self.sess.buffer_lint_with_diagnostic( + self.resolver.lint_buffer().buffer_lint_with_diagnostic( ELIDED_LIFETIMES_IN_PATHS, CRATE_NODE_ID, path_span, @@ -3346,7 +3349,7 @@ impl<'a> LoweringContext<'a> { } } - fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) { + fn maybe_lint_bare_trait(&mut self, span: Span, id: NodeId, is_global: bool) { // FIXME(davidtwco): This is a hack to detect macros which produce spans of the // call site which do not have a macro backtrace. See #61963. let is_macro_callsite = self.sess.source_map() @@ -3354,7 +3357,7 @@ impl<'a> LoweringContext<'a> { .map(|snippet| snippet.starts_with("#[")) .unwrap_or(true); if !is_macro_callsite { - self.sess.buffer_lint_with_diagnostic( + self.resolver.lint_buffer().buffer_lint_with_diagnostic( builtin::BARE_TRAIT_OBJECTS, id, span, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd2460cfab116..03fc0e95b5f1b 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -363,7 +363,7 @@ impl Session { self.diagnostic().span_note_without_error(sp, msg) } - pub fn buffer_lint>( + pub fn buffer_lint_late>( &self, lint: &'static lint::Lint, id: ast::NodeId, @@ -372,13 +372,13 @@ impl Session { ) { match *self.buffered_lints.borrow_mut() { Some(ref mut buffer) => { - buffer.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal) + buffer.buffer_lint(lint, id, sp, msg); } None => bug!("can't buffer lints after HIR lowering"), } } - pub fn buffer_lint_with_diagnostic>( + pub fn buffer_lint_with_diagnostic_late>( &self, lint: &'static lint::Lint, id: ast::NodeId, @@ -387,7 +387,9 @@ impl Session { diagnostic: BuiltinLintDiagnostics, ) { match *self.buffered_lints.borrow_mut() { - Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), msg, diagnostic), + Some(ref mut buffer) => buffer.buffer_lint_with_diagnostic( + lint, id, sp.into(), msg, diagnostic, + ), None => bug!("can't buffer lints after HIR lowering"), } } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 8f11dc9372728..1967465932523 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -559,7 +559,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Vec hir::lowering::Resolver for Resolver<'a> { let expn_id = self.definitions.expansion_that_defined(def_id.index); self.has_derives(expn_id, derives) } + + fn lint_buffer(&mut self) -> &mut lint::LintBuffer { + &mut self.lint_buffer + } } impl<'a> Resolver<'a> { From 0c05ed29fd26eb1a7cc5fa77c0fa41d940a78346 Mon Sep 17 00:00:00 2001 From: matthewjasper Date: Fri, 25 Oct 2019 18:50:40 +0100 Subject: [PATCH 15/22] Apply suggestions from code review Co-Authored-By: Mazdak Farrokhzad --- src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs index b22d216553389..2b4f5e0975ac3 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs @@ -1,6 +1,6 @@ -// Test that an impl trait type that expands to itself is an error. +// Test that an `impl Trait` type that expands to itself is an error. -fn test() -> impl Sized { //~ ERROR E0720 +fn test() -> impl Sized { //~ ERROR E0720 test() } From 9f257ddca523f97b2bd5e2ba9255f9800c9658c0 Mon Sep 17 00:00:00 2001 From: Pi Lanningham Date: Fri, 25 Oct 2019 00:35:17 -0400 Subject: [PATCH 16/22] Renamed ui/dead-code-ret to ui/unreachable-code-ret This test was actually about the unreachable_code flag, not dead_code, so I renamed it for clarity (to prepare for the next commit, where I plan to move a bunch of the dead_code tests to a single folder) --- src/test/ui/{dead-code-ret.rs => unreachable-code-ret.rs} | 0 .../ui/{dead-code-ret.stderr => unreachable-code-ret.stderr} | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/test/ui/{dead-code-ret.rs => unreachable-code-ret.rs} (100%) rename src/test/ui/{dead-code-ret.stderr => unreachable-code-ret.stderr} (86%) diff --git a/src/test/ui/dead-code-ret.rs b/src/test/ui/unreachable-code-ret.rs similarity index 100% rename from src/test/ui/dead-code-ret.rs rename to src/test/ui/unreachable-code-ret.rs diff --git a/src/test/ui/dead-code-ret.stderr b/src/test/ui/unreachable-code-ret.stderr similarity index 86% rename from src/test/ui/dead-code-ret.stderr rename to src/test/ui/unreachable-code-ret.stderr index 83841131599b2..c22342ce7218d 100644 --- a/src/test/ui/dead-code-ret.stderr +++ b/src/test/ui/unreachable-code-ret.stderr @@ -1,5 +1,5 @@ error: unreachable statement - --> $DIR/dead-code-ret.rs:7:5 + --> $DIR/unreachable-code-ret.rs:7:5 | LL | return; | ------ any code following this expression is unreachable @@ -7,7 +7,7 @@ LL | println!("Paul is dead"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement | note: lint level defined here - --> $DIR/dead-code-ret.rs:3:9 + --> $DIR/unreachable-code-ret.rs:3:9 | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ From cb5fd4ee4ee489d3cfb09d48581103e1106512e2 Mon Sep 17 00:00:00 2001 From: Pi Lanningham Date: Fri, 25 Oct 2019 00:42:05 -0400 Subject: [PATCH 17/22] Move dead_code related tests to test/ui/dead-code This helps organize the tests better. I also renamed several of the tests to remove redundant dead-code in the path, and better match what they're testing --- .../dead-code/alias-in-pat.rs} | 0 .../dead-code/associated-type.rs} | 0 .../ui/{fail-no-dead-code.rs => lint/dead-code/basic.rs} | 0 .../dead-code/basic.stderr} | 4 ++-- .../dead-code/closure-bang.rs} | 0 .../const-and-self.rs} | 0 .../empty-unused-enum.rs} | 0 .../empty-unused-enum.stderr} | 4 ++-- .../empty-unused-public-enum.rs} | 0 .../dead-code/enum-variants.rs} | 0 .../impl-trait.rs} | 0 .../impl-trait.stderr} | 4 ++-- .../dead-code/leading-underscore.rs} | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-1.rs | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-1.stderr | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-2.rs | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-2.stderr | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-3.rs | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-3.stderr | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-4.rs | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-4.stderr | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-5.rs | 0 src/test/ui/lint/{ => dead-code}/lint-dead-code-5.stderr | 0 .../dead-code/tuple-struct-field.rs} | 0 .../type-alias.rs} | 0 .../type-alias.stderr} | 4 ++-- .../unused-enum.rs} | 0 .../unused-enum.stderr} | 8 ++++---- .../unused-struct-variant.rs} | 0 .../unused-struct-variant.stderr} | 4 ++-- .../unused-variant-pub.rs} | 0 .../unused-variant.rs} | 0 .../unused-variant.stderr} | 4 ++-- .../dead-code/with-core-crate.rs} | 0 .../dead-code/with-core-crate.stderr} | 4 ++-- .../ui/{dead-code-impl.rs => lint/dead-code/with-impl.rs} | 0 36 files changed, 18 insertions(+), 18 deletions(-) rename src/test/ui/{dead-code-alias-in-pat.rs => lint/dead-code/alias-in-pat.rs} (100%) rename src/test/ui/{lint-dead-code-associated-type.rs => lint/dead-code/associated-type.rs} (100%) rename src/test/ui/{fail-no-dead-code.rs => lint/dead-code/basic.rs} (100%) rename src/test/ui/{fail-no-dead-code.stderr => lint/dead-code/basic.stderr} (73%) rename src/test/ui/{dead-code-closure-bang.rs => lint/dead-code/closure-bang.rs} (100%) rename src/test/ui/lint/{lint-dead-code-const-and-self.rs => dead-code/const-and-self.rs} (100%) rename src/test/ui/lint/{lint-dead-code-empty-unused-enum.rs => dead-code/empty-unused-enum.rs} (100%) rename src/test/ui/lint/{lint-dead-code-empty-unused-enum.stderr => dead-code/empty-unused-enum.stderr} (70%) rename src/test/ui/lint/{lint-dead-code-empty-unused-enum-pub.rs => dead-code/empty-unused-public-enum.rs} (100%) rename src/test/ui/{lint-dead-code-variant.rs => lint/dead-code/enum-variants.rs} (100%) rename src/test/ui/lint/{lint-dead-code-impl-trait.rs => dead-code/impl-trait.rs} (100%) rename src/test/ui/lint/{lint-dead-code-impl-trait.stderr => dead-code/impl-trait.stderr} (71%) rename src/test/ui/{dead-code-leading-underscore.rs => lint/dead-code/leading-underscore.rs} (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-1.rs (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-1.stderr (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-2.rs (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-2.stderr (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-3.rs (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-3.stderr (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-4.rs (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-4.stderr (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-5.rs (100%) rename src/test/ui/lint/{ => dead-code}/lint-dead-code-5.stderr (100%) rename src/test/ui/{dead-code-tuple-struct-field.rs => lint/dead-code/tuple-struct-field.rs} (100%) rename src/test/ui/lint/{lint-dead-code-type-alias.rs => dead-code/type-alias.rs} (100%) rename src/test/ui/lint/{lint-dead-code-type-alias.stderr => dead-code/type-alias.stderr} (71%) rename src/test/ui/lint/{lint-dead-code-unused-enum.rs => dead-code/unused-enum.rs} (100%) rename src/test/ui/lint/{lint-dead-code-unused-enum.stderr => dead-code/unused-enum.stderr} (68%) rename src/test/ui/lint/{lint-dead-code-unused-variant.rs => dead-code/unused-struct-variant.rs} (100%) rename src/test/ui/lint/{lint-dead-code-unused-variant.stderr => dead-code/unused-struct-variant.stderr} (73%) rename src/test/ui/lint/{lint-dead-code-unused-variant-pub.rs => dead-code/unused-variant-pub.rs} (100%) rename src/test/ui/lint/{lint-dead-code-variant.rs => dead-code/unused-variant.rs} (100%) rename src/test/ui/lint/{lint-dead-code-variant.stderr => dead-code/unused-variant.stderr} (72%) rename src/test/ui/{fail-no-dead-code-core.rs => lint/dead-code/with-core-crate.rs} (100%) rename src/test/ui/{fail-no-dead-code-core.stderr => lint/dead-code/with-core-crate.stderr} (70%) rename src/test/ui/{dead-code-impl.rs => lint/dead-code/with-impl.rs} (100%) diff --git a/src/test/ui/dead-code-alias-in-pat.rs b/src/test/ui/lint/dead-code/alias-in-pat.rs similarity index 100% rename from src/test/ui/dead-code-alias-in-pat.rs rename to src/test/ui/lint/dead-code/alias-in-pat.rs diff --git a/src/test/ui/lint-dead-code-associated-type.rs b/src/test/ui/lint/dead-code/associated-type.rs similarity index 100% rename from src/test/ui/lint-dead-code-associated-type.rs rename to src/test/ui/lint/dead-code/associated-type.rs diff --git a/src/test/ui/fail-no-dead-code.rs b/src/test/ui/lint/dead-code/basic.rs similarity index 100% rename from src/test/ui/fail-no-dead-code.rs rename to src/test/ui/lint/dead-code/basic.rs diff --git a/src/test/ui/fail-no-dead-code.stderr b/src/test/ui/lint/dead-code/basic.stderr similarity index 73% rename from src/test/ui/fail-no-dead-code.stderr rename to src/test/ui/lint/dead-code/basic.stderr index 8babcffaa8dd7..e5d1af12cf284 100644 --- a/src/test/ui/fail-no-dead-code.stderr +++ b/src/test/ui/lint/dead-code/basic.stderr @@ -1,11 +1,11 @@ error: function is never used: `foo` - --> $DIR/fail-no-dead-code.rs:4:1 + --> $DIR/basic.rs:4:1 | LL | fn foo() { | ^^^^^^^^ | note: lint level defined here - --> $DIR/fail-no-dead-code.rs:1:9 + --> $DIR/basic.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/dead-code-closure-bang.rs b/src/test/ui/lint/dead-code/closure-bang.rs similarity index 100% rename from src/test/ui/dead-code-closure-bang.rs rename to src/test/ui/lint/dead-code/closure-bang.rs diff --git a/src/test/ui/lint/lint-dead-code-const-and-self.rs b/src/test/ui/lint/dead-code/const-and-self.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-const-and-self.rs rename to src/test/ui/lint/dead-code/const-and-self.rs diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum.rs b/src/test/ui/lint/dead-code/empty-unused-enum.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-empty-unused-enum.rs rename to src/test/ui/lint/dead-code/empty-unused-enum.rs diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr b/src/test/ui/lint/dead-code/empty-unused-enum.stderr similarity index 70% rename from src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr rename to src/test/ui/lint/dead-code/empty-unused-enum.stderr index 4e3bebfc48bde..17bbdfc71a260 100644 --- a/src/test/ui/lint/lint-dead-code-empty-unused-enum.stderr +++ b/src/test/ui/lint/dead-code/empty-unused-enum.stderr @@ -1,11 +1,11 @@ error: enum is never used: `E` - --> $DIR/lint-dead-code-empty-unused-enum.rs:3:1 + --> $DIR/empty-unused-enum.rs:3:1 | LL | enum E {} | ^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-empty-unused-enum.rs:1:9 + --> $DIR/empty-unused-enum.rs:1:9 | LL | #![deny(unused)] | ^^^^^^ diff --git a/src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs b/src/test/ui/lint/dead-code/empty-unused-public-enum.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-empty-unused-enum-pub.rs rename to src/test/ui/lint/dead-code/empty-unused-public-enum.rs diff --git a/src/test/ui/lint-dead-code-variant.rs b/src/test/ui/lint/dead-code/enum-variants.rs similarity index 100% rename from src/test/ui/lint-dead-code-variant.rs rename to src/test/ui/lint/dead-code/enum-variants.rs diff --git a/src/test/ui/lint/lint-dead-code-impl-trait.rs b/src/test/ui/lint/dead-code/impl-trait.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-impl-trait.rs rename to src/test/ui/lint/dead-code/impl-trait.rs diff --git a/src/test/ui/lint/lint-dead-code-impl-trait.stderr b/src/test/ui/lint/dead-code/impl-trait.stderr similarity index 71% rename from src/test/ui/lint/lint-dead-code-impl-trait.stderr rename to src/test/ui/lint/dead-code/impl-trait.stderr index 61d0954bf3146..f2a78cc65e26e 100644 --- a/src/test/ui/lint/lint-dead-code-impl-trait.stderr +++ b/src/test/ui/lint/dead-code/impl-trait.stderr @@ -1,11 +1,11 @@ error: type alias is never used: `Unused` - --> $DIR/lint-dead-code-impl-trait.rs:12:1 + --> $DIR/impl-trait.rs:12:1 | LL | type Unused = (); | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-impl-trait.rs:1:9 + --> $DIR/impl-trait.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/dead-code-leading-underscore.rs b/src/test/ui/lint/dead-code/leading-underscore.rs similarity index 100% rename from src/test/ui/dead-code-leading-underscore.rs rename to src/test/ui/lint/dead-code/leading-underscore.rs diff --git a/src/test/ui/lint/lint-dead-code-1.rs b/src/test/ui/lint/dead-code/lint-dead-code-1.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-1.rs rename to src/test/ui/lint/dead-code/lint-dead-code-1.rs diff --git a/src/test/ui/lint/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr similarity index 100% rename from src/test/ui/lint/lint-dead-code-1.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-1.stderr diff --git a/src/test/ui/lint/lint-dead-code-2.rs b/src/test/ui/lint/dead-code/lint-dead-code-2.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-2.rs rename to src/test/ui/lint/dead-code/lint-dead-code-2.rs diff --git a/src/test/ui/lint/lint-dead-code-2.stderr b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr similarity index 100% rename from src/test/ui/lint/lint-dead-code-2.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-2.stderr diff --git a/src/test/ui/lint/lint-dead-code-3.rs b/src/test/ui/lint/dead-code/lint-dead-code-3.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-3.rs rename to src/test/ui/lint/dead-code/lint-dead-code-3.rs diff --git a/src/test/ui/lint/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr similarity index 100% rename from src/test/ui/lint/lint-dead-code-3.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-3.stderr diff --git a/src/test/ui/lint/lint-dead-code-4.rs b/src/test/ui/lint/dead-code/lint-dead-code-4.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-4.rs rename to src/test/ui/lint/dead-code/lint-dead-code-4.rs diff --git a/src/test/ui/lint/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr similarity index 100% rename from src/test/ui/lint/lint-dead-code-4.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-4.stderr diff --git a/src/test/ui/lint/lint-dead-code-5.rs b/src/test/ui/lint/dead-code/lint-dead-code-5.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-5.rs rename to src/test/ui/lint/dead-code/lint-dead-code-5.rs diff --git a/src/test/ui/lint/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr similarity index 100% rename from src/test/ui/lint/lint-dead-code-5.stderr rename to src/test/ui/lint/dead-code/lint-dead-code-5.stderr diff --git a/src/test/ui/dead-code-tuple-struct-field.rs b/src/test/ui/lint/dead-code/tuple-struct-field.rs similarity index 100% rename from src/test/ui/dead-code-tuple-struct-field.rs rename to src/test/ui/lint/dead-code/tuple-struct-field.rs diff --git a/src/test/ui/lint/lint-dead-code-type-alias.rs b/src/test/ui/lint/dead-code/type-alias.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-type-alias.rs rename to src/test/ui/lint/dead-code/type-alias.rs diff --git a/src/test/ui/lint/lint-dead-code-type-alias.stderr b/src/test/ui/lint/dead-code/type-alias.stderr similarity index 71% rename from src/test/ui/lint/lint-dead-code-type-alias.stderr rename to src/test/ui/lint/dead-code/type-alias.stderr index 4198ddfb6cb03..82df23bd9448b 100644 --- a/src/test/ui/lint/lint-dead-code-type-alias.stderr +++ b/src/test/ui/lint/dead-code/type-alias.stderr @@ -1,11 +1,11 @@ error: type alias is never used: `Unused` - --> $DIR/lint-dead-code-type-alias.rs:4:1 + --> $DIR/type-alias.rs:4:1 | LL | type Unused = u8; | ^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-type-alias.rs:1:9 + --> $DIR/type-alias.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/lint/lint-dead-code-unused-enum.rs b/src/test/ui/lint/dead-code/unused-enum.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-unused-enum.rs rename to src/test/ui/lint/dead-code/unused-enum.rs diff --git a/src/test/ui/lint/lint-dead-code-unused-enum.stderr b/src/test/ui/lint/dead-code/unused-enum.stderr similarity index 68% rename from src/test/ui/lint/lint-dead-code-unused-enum.stderr rename to src/test/ui/lint/dead-code/unused-enum.stderr index ea711e7b05ee6..682dfcf588182 100644 --- a/src/test/ui/lint/lint-dead-code-unused-enum.stderr +++ b/src/test/ui/lint/dead-code/unused-enum.stderr @@ -1,24 +1,24 @@ error: struct is never constructed: `F` - --> $DIR/lint-dead-code-unused-enum.rs:3:1 + --> $DIR/unused-enum.rs:3:1 | LL | struct F; | ^^^^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-unused-enum.rs:1:9 + --> $DIR/unused-enum.rs:1:9 | LL | #![deny(unused)] | ^^^^^^ = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` error: struct is never constructed: `B` - --> $DIR/lint-dead-code-unused-enum.rs:4:1 + --> $DIR/unused-enum.rs:4:1 | LL | struct B; | ^^^^^^^^^ error: enum is never used: `E` - --> $DIR/lint-dead-code-unused-enum.rs:6:1 + --> $DIR/unused-enum.rs:6:1 | LL | enum E { | ^^^^^^ diff --git a/src/test/ui/lint/lint-dead-code-unused-variant.rs b/src/test/ui/lint/dead-code/unused-struct-variant.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-unused-variant.rs rename to src/test/ui/lint/dead-code/unused-struct-variant.rs diff --git a/src/test/ui/lint/lint-dead-code-unused-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr similarity index 73% rename from src/test/ui/lint/lint-dead-code-unused-variant.stderr rename to src/test/ui/lint/dead-code/unused-struct-variant.stderr index 919996ec30020..0037592e3de06 100644 --- a/src/test/ui/lint/lint-dead-code-unused-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr @@ -1,11 +1,11 @@ error: variant is never constructed: `Bar` - --> $DIR/lint-dead-code-unused-variant.rs:8:5 + --> $DIR/unused-struct-variant.rs:8:5 | LL | Bar(B), | ^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-unused-variant.rs:1:9 + --> $DIR/unused-struct-variant.rs:1:9 | LL | #![deny(unused)] | ^^^^^^ diff --git a/src/test/ui/lint/lint-dead-code-unused-variant-pub.rs b/src/test/ui/lint/dead-code/unused-variant-pub.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-unused-variant-pub.rs rename to src/test/ui/lint/dead-code/unused-variant-pub.rs diff --git a/src/test/ui/lint/lint-dead-code-variant.rs b/src/test/ui/lint/dead-code/unused-variant.rs similarity index 100% rename from src/test/ui/lint/lint-dead-code-variant.rs rename to src/test/ui/lint/dead-code/unused-variant.rs diff --git a/src/test/ui/lint/lint-dead-code-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr similarity index 72% rename from src/test/ui/lint/lint-dead-code-variant.stderr rename to src/test/ui/lint/dead-code/unused-variant.stderr index a79432dc68d6a..2167b9d910d94 100644 --- a/src/test/ui/lint/lint-dead-code-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-variant.stderr @@ -1,11 +1,11 @@ error: variant is never constructed: `Variant1` - --> $DIR/lint-dead-code-variant.rs:5:5 + --> $DIR/unused-variant.rs:5:5 | LL | Variant1, | ^^^^^^^^ | note: lint level defined here - --> $DIR/lint-dead-code-variant.rs:1:9 + --> $DIR/unused-variant.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/fail-no-dead-code-core.rs b/src/test/ui/lint/dead-code/with-core-crate.rs similarity index 100% rename from src/test/ui/fail-no-dead-code-core.rs rename to src/test/ui/lint/dead-code/with-core-crate.rs diff --git a/src/test/ui/fail-no-dead-code-core.stderr b/src/test/ui/lint/dead-code/with-core-crate.stderr similarity index 70% rename from src/test/ui/fail-no-dead-code-core.stderr rename to src/test/ui/lint/dead-code/with-core-crate.stderr index 2540242f9f68b..30caac3cd0148 100644 --- a/src/test/ui/fail-no-dead-code-core.stderr +++ b/src/test/ui/lint/dead-code/with-core-crate.stderr @@ -1,11 +1,11 @@ error: function is never used: `foo` - --> $DIR/fail-no-dead-code-core.rs:7:1 + --> $DIR/with-core-crate.rs:7:1 | LL | fn foo() { | ^^^^^^^^ | note: lint level defined here - --> $DIR/fail-no-dead-code-core.rs:1:9 + --> $DIR/with-core-crate.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ diff --git a/src/test/ui/dead-code-impl.rs b/src/test/ui/lint/dead-code/with-impl.rs similarity index 100% rename from src/test/ui/dead-code-impl.rs rename to src/test/ui/lint/dead-code/with-impl.rs From 402a8af1d59a573ebd40cd953a779013969ec313 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 25 Oct 2019 19:27:57 -0400 Subject: [PATCH 18/22] Remove lint callback from driver This is leftover from a restructuring of lint registration for drivers; it should now happen via the register_lints field on Config rather than this function. --- src/librustc_driver/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 15adf7e4add73..6e8bc11162f66 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -106,8 +106,6 @@ pub fn abort_on_err(result: Result, sess: &Session) -> T { pub trait Callbacks { /// Called before creating the compiler instance fn config(&mut self, _config: &mut interface::Config) {} - /// Called early during compilation to allow other drivers to easily register lints. - fn extra_lints(&mut self, _ls: &mut lint::LintStore) {} /// Called after parsing. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) fn after_parsing(&mut self, _compiler: &interface::Compiler) -> Compilation { From 8f988bd92cf7d6d3e9be5310c18e472ba297e247 Mon Sep 17 00:00:00 2001 From: Ohad Ravid Date: Wed, 23 Oct 2019 22:22:13 +0200 Subject: [PATCH 19/22] Coherence should allow fundamental types to impl traits --- src/librustc/traits/coherence.rs | 14 ++++++++++---- ...pl-foreign-for-locally-defined-fundamental.rs | 16 ++++++++++++++++ ...n-for-locally-defined-fundamental[foreign].rs | 16 ++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs create mode 100644 src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 4696d4da58ec0..2734fce4ea55a 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -378,15 +378,21 @@ fn orphan_check_trait_ref<'tcx>( // Let Ti be the first such type. // - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti) // - fn uncover_fundamental_ty(ty: Ty<'_>) -> Vec> { - if fundamental_ty(ty) { - ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(ty)).collect() + fn uncover_fundamental_ty<'a>( + tcx: TyCtxt<'_>, + ty: Ty<'a>, + in_crate: InCrate, + ) -> Vec> { + if fundamental_ty(ty) && !ty_is_local(tcx, ty, in_crate) { + ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).collect() } else { vec![ty] } } - for input_ty in trait_ref.input_types().flat_map(uncover_fundamental_ty) { + for input_ty in + trait_ref.input_types().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)) + { debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty); if ty_is_local(tcx, input_ty, in_crate) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); diff --git a/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs new file mode 100644 index 0000000000000..d461b5abd60ff --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs @@ -0,0 +1,16 @@ +#![feature(fundamental)] +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; + +#[fundamental] +struct Local; + +impl Remote for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs new file mode 100644 index 0000000000000..0a3d9e2e0e89c --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs @@ -0,0 +1,16 @@ +#![feature(fundamental)] +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; + +#[fundamental] +struct MyBox(T); + +impl Remote for MyBox {} + +fn main() {} From 2ac9b7a424d134108d98130d4a326295f5dfe68b Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 25 Oct 2019 13:23:18 -0400 Subject: [PATCH 20/22] Move crate type checking later This allows us to directly pass in a lint buffer --- src/librustc/session/config.rs | 2 +- src/librustc_interface/passes.rs | 2 + src/librustc_interface/util.rs | 109 +++++++++++++++++-------------- 3 files changed, 62 insertions(+), 51 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 33b9ddaa62230..2bcddeaf1962d 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1469,7 +1469,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, (such as entering an empty infinite loop) by inserting llvm.sideeffect"), } -pub fn default_lib_output() -> CrateType { +pub const fn default_lib_output() -> CrateType { CrateType::Rlib } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 6e37c0302f310..b08562ee11a68 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -295,6 +295,8 @@ fn configure_and_expand_inner<'a>( krate }); + util::check_attr_crate_type(&krate.attrs, &mut resolver.lint_buffer); + syntax_ext::plugin_macro_defs::inject( &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition() ); diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 1967465932523..d0c15073f1640 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -526,6 +526,63 @@ pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguat CrateDisambiguator::from(hasher.finish::()) } +pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut lint::LintBuffer) { + // Unconditionally collect crate types from attributes to make them used + for a in attrs.iter() { + if a.check_name(sym::crate_type) { + if let Some(n) = a.value_str() { + if let Some(_) = categorize_crate_type(n) { + return; + } + + if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind { + let span = spanned.span; + let lev_candidate = find_best_match_for_name( + CRATE_TYPES.iter().map(|(k, _)| k), + &n.as_str(), + None + ); + if let Some(candidate) = lev_candidate { + lint_buffer.buffer_lint_with_diagnostic( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + "invalid `crate_type` value", + lint::builtin::BuiltinLintDiagnostics:: + UnknownCrateTypes( + span, + "did you mean".to_string(), + format!("\"{}\"", candidate) + ) + ); + } else { + lint_buffer.buffer_lint( + lint::builtin::UNKNOWN_CRATE_TYPES, + ast::CRATE_NODE_ID, + span, + "invalid `crate_type` value" + ); + } + } + } + } + } +} + +const CRATE_TYPES: &[(Symbol, config::CrateType)] = &[ + (sym::rlib, config::CrateType::Rlib), + (sym::dylib, config::CrateType::Dylib), + (sym::cdylib, config::CrateType::Cdylib), + (sym::lib, config::default_lib_output()), + (sym::staticlib, config::CrateType::Staticlib), + (sym::proc_dash_macro, config::CrateType::ProcMacro), + (sym::bin, config::CrateType::Executable), +]; + +fn categorize_crate_type(s: Symbol) -> Option { + Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1) +} + pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { // Unconditionally collect crate types from attributes to make them used let attr_types: Vec = attrs @@ -533,56 +590,8 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Some(config::CrateType::Rlib), - Some(sym::dylib) => Some(config::CrateType::Dylib), - Some(sym::cdylib) => Some(config::CrateType::Cdylib), - Some(sym::lib) => Some(config::default_lib_output()), - Some(sym::staticlib) => Some(config::CrateType::Staticlib), - Some(sym::proc_dash_macro) => Some(config::CrateType::ProcMacro), - Some(sym::bin) => Some(config::CrateType::Executable), - Some(n) => { - let crate_types = vec![ - sym::rlib, - sym::dylib, - sym::cdylib, - sym::lib, - sym::staticlib, - sym::proc_dash_macro, - sym::bin - ]; - - if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind { - let span = spanned.span; - let lev_candidate = find_best_match_for_name( - crate_types.iter(), - &n.as_str(), - None - ); - if let Some(candidate) = lev_candidate { - session.buffer_lint_with_diagnostic_late( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - span, - "invalid `crate_type` value", - lint::builtin::BuiltinLintDiagnostics:: - UnknownCrateTypes( - span, - "did you mean".to_string(), - format!("\"{}\"", candidate) - ) - ); - } else { - session.buffer_lint_late( - lint::builtin::UNKNOWN_CRATE_TYPES, - ast::CRATE_NODE_ID, - span, - "invalid `crate_type` value" - ); - } - } - None - } - None => None + Some(s) => categorize_crate_type(s), + _ => None, } } else { None From a44126a3402cac2ec8269f8c8afee685a66c0e59 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 25 Oct 2019 13:41:51 -0400 Subject: [PATCH 21/22] Delete lint buffer from Session --- src/librustc/lint/context.rs | 26 ++++++++++----------- src/librustc/lint/levels.rs | 16 +++++++++---- src/librustc/lint/mod.rs | 2 +- src/librustc/session/mod.rs | 40 -------------------------------- src/librustc_interface/passes.rs | 12 +++++----- src/librustc_resolve/lib.rs | 11 +++++---- 6 files changed, 39 insertions(+), 68 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 1cb53d754dcd3..eef1cee8db37a 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -34,7 +34,6 @@ use crate::util::common::time; use errors::DiagnosticBuilder; use std::slice; -use std::default::Default as StdDefault; use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter}; use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use syntax::ast; @@ -584,12 +583,13 @@ impl<'a> EarlyContext<'a> { lint_store: &'a LintStore, krate: &'a ast::Crate, buffered: LintBuffer, + warn_about_weird_lints: bool, ) -> EarlyContext<'a> { EarlyContext { sess, krate, lint_store, - builder: LintLevelSets::builder(sess, lint_store), + builder: LintLevelSets::builder(sess, warn_about_weird_lints, lint_store), buffered, } } @@ -1490,9 +1490,10 @@ fn early_lint_crate( krate: &ast::Crate, pass: T, buffered: LintBuffer, + warn_about_weird_lints: bool, ) -> LintBuffer { let mut cx = EarlyContextAndPass { - context: EarlyContext::new(sess, lint_store, krate, buffered), + context: EarlyContext::new(sess, lint_store, krate, buffered, warn_about_weird_lints), pass, }; @@ -1514,22 +1515,19 @@ pub fn check_ast_crate( lint_store: &LintStore, krate: &ast::Crate, pre_expansion: bool, + lint_buffer: Option, builtin_lints: T, ) { - let (mut passes, mut buffered): (Vec<_>, _) = if pre_expansion { - ( - lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect(), - LintBuffer::default(), - ) + let mut passes: Vec<_> = if pre_expansion { + lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect() } else { - ( - lint_store.early_passes.iter().map(|p| (p)()).collect(), - sess.buffered_lints.borrow_mut().take().unwrap(), - ) + lint_store.early_passes.iter().map(|p| (p)()).collect() }; + let mut buffered = lint_buffer.unwrap_or_default(); if !sess.opts.debugging_opts.no_interleave_lints { - buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered); + buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered, + pre_expansion); if !passes.is_empty() { buffered = early_lint_crate( @@ -1538,6 +1536,7 @@ pub fn check_ast_crate( krate, EarlyLintPassObjects { lints: &mut passes[..] }, buffered, + pre_expansion, ); } } else { @@ -1549,6 +1548,7 @@ pub fn check_ast_crate( krate, EarlyLintPassObjects { lints: slice::from_mut(pass) }, buffered, + pre_expansion, ) }); } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 4c60492e470c2..e470dbdf3239b 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -44,8 +44,12 @@ impl LintLevelSets { return me } - pub fn builder<'a>(sess: &'a Session, store: &LintStore) -> LintLevelsBuilder<'a> { - LintLevelsBuilder::new(sess, LintLevelSets::new(sess, store)) + pub fn builder<'a>( + sess: &'a Session, + warn_about_weird_lints: bool, + store: &LintStore, + ) -> LintLevelsBuilder<'a> { + LintLevelsBuilder::new(sess, warn_about_weird_lints, LintLevelSets::new(sess, store)) } fn process_command_line(&mut self, sess: &Session, store: &LintStore) { @@ -160,14 +164,18 @@ pub struct BuilderPush { } impl<'a> LintLevelsBuilder<'a> { - pub fn new(sess: &'a Session, sets: LintLevelSets) -> LintLevelsBuilder<'a> { + pub fn new( + sess: &'a Session, + warn_about_weird_lints: bool, + sets: LintLevelSets, + ) -> LintLevelsBuilder<'a> { assert_eq!(sets.list.len(), 1); LintLevelsBuilder { sess, sets, cur: 0, id_to_set: Default::default(), - warn_about_weird_lints: sess.buffered_lints.borrow().is_some(), + warn_about_weird_lints, } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 9fdb09023290c..30e96428db779 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -795,7 +795,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { assert_eq!(cnum, LOCAL_CRATE); let store = &tcx.lint_store; let mut builder = LintLevelMapBuilder { - levels: LintLevelSets::builder(tcx.sess, &store), + levels: LintLevelSets::builder(tcx.sess, false, &store), tcx: tcx, store: store, }; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 03fc0e95b5f1b..d4ddbe43c3612 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -6,7 +6,6 @@ use crate::hir::def_id::CrateNum; use rustc_data_structures::fingerprint::Fingerprint; use crate::lint; -use crate::lint::builtin::BuiltinLintDiagnostics; use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath}; use crate::session::search_paths::{PathKind, SearchPath}; use crate::util::nodemap::{FxHashMap, FxHashSet}; @@ -77,13 +76,6 @@ pub struct Session { /// if the value stored here has been affected by path remapping. pub working_dir: (PathBuf, bool), - /// This is intended to be used from a single thread. - /// - /// FIXME: there was a previous comment about this not being thread safe, - /// but it's not clear how or why that's the case. The LintBuffer itself is certainly thread - /// safe at least from a "Rust safety" standpoint. - pub buffered_lints: Lock>, - /// Set of `(DiagnosticId, Option, message)` tuples tracking /// (sub)diagnostics that have been set once, but should not be set again, /// in order to avoid redundantly verbose output (Issue #24690, #44953). @@ -363,37 +355,6 @@ impl Session { self.diagnostic().span_note_without_error(sp, msg) } - pub fn buffer_lint_late>( - &self, - lint: &'static lint::Lint, - id: ast::NodeId, - sp: S, - msg: &str, - ) { - match *self.buffered_lints.borrow_mut() { - Some(ref mut buffer) => { - buffer.buffer_lint(lint, id, sp, msg); - } - None => bug!("can't buffer lints after HIR lowering"), - } - } - - pub fn buffer_lint_with_diagnostic_late>( - &self, - lint: &'static lint::Lint, - id: ast::NodeId, - sp: S, - msg: &str, - diagnostic: BuiltinLintDiagnostics, - ) { - match *self.buffered_lints.borrow_mut() { - Some(ref mut buffer) => buffer.buffer_lint_with_diagnostic( - lint, id, sp.into(), msg, diagnostic, - ), - None => bug!("can't buffer lints after HIR lowering"), - } - } - pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId { let id = self.next_node_id.get(); @@ -1217,7 +1178,6 @@ fn build_session_( sysroot, local_crate_source_file, working_dir, - buffered_lints: Lock::new(Some(Default::default())), one_time_diagnostics: Default::default(), plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())), plugin_attributes: Lock::new(Vec::new()), diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index b08562ee11a68..cb498285c1903 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -267,17 +267,16 @@ fn configure_and_expand_inner<'a>( lint_store, &krate, true, + None, rustc_lint::BuiltinCombinedPreExpansionLintPass::new()); }); - let lint_buffer = lint::LintBuffer::default(); let mut resolver = Resolver::new( sess, &krate, crate_name, metadata_loader, &resolver_arenas, - lint_buffer, ); syntax_ext::register_builtin_macros(&mut resolver, sess.edition()); @@ -295,7 +294,7 @@ fn configure_and_expand_inner<'a>( krate }); - util::check_attr_crate_type(&krate.attrs, &mut resolver.lint_buffer); + util::check_attr_crate_type(&krate.attrs, &mut resolver.lint_buffer()); syntax_ext::plugin_macro_defs::inject( &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition() @@ -370,7 +369,7 @@ fn configure_and_expand_inner<'a>( for span in missing_fragment_specifiers { let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; let msg = "missing fragment specifier"; - resolver.lint_buffer.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg); + resolver.lint_buffer().buffer_lint(lint, ast::CRATE_NODE_ID, span, msg); } if cfg!(windows) { env::set_var("PATH", &old_path); @@ -399,7 +398,7 @@ fn configure_and_expand_inner<'a>( } let has_proc_macro_decls = time(sess, "AST validation", || { - ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer) + ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer()) }); @@ -468,7 +467,7 @@ fn configure_and_expand_inner<'a>( info!("{} parse sess buffered_lints", buffered_lints.len()); for BufferedEarlyLint{id, span, msg, lint_id} in buffered_lints.drain(..) { let lint = lint::Lint::from_parser_lint_id(lint_id); - resolver.lint_buffer.buffer_lint(lint, id, span, &msg); + resolver.lint_buffer().buffer_lint(lint, id, span, &msg); } }); @@ -500,6 +499,7 @@ pub fn lower_to_hir( lint_store, &krate, false, + Some(std::mem::take(resolver.lint_buffer())), rustc_lint::BuiltinCombinedEarlyLintPass::new(), ) }); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 79842118065c0..5d868e9274019 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -962,7 +962,7 @@ pub struct Resolver<'a> { /// when visiting the correspondent variants. variant_vis: DefIdMap, - pub lint_buffer: lint::LintBuffer, + lint_buffer: lint::LintBuffer, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1093,8 +1093,7 @@ impl<'a> Resolver<'a> { krate: &Crate, crate_name: &str, metadata_loader: &'a MetadataLoaderDyn, - arenas: &'a ResolverArenas<'a>, - lint_buffer: lint::LintBuffer) + arenas: &'a ResolverArenas<'a>) -> Resolver<'a> { let root_def_id = DefId::local(CRATE_DEF_INDEX); let root_module_kind = ModuleKind::Def( @@ -1234,10 +1233,14 @@ impl<'a> Resolver<'a> { .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat)) .collect(), variant_vis: Default::default(), - lint_buffer, + lint_buffer: lint::LintBuffer::default(), } } + pub fn lint_buffer(&mut self) -> &mut lint::LintBuffer { + &mut self.lint_buffer + } + pub fn arenas() -> ResolverArenas<'a> { Default::default() } From 94890d233d59b1c0f2cca6d60c564898e9a2bdcf Mon Sep 17 00:00:00 2001 From: Pi Lanningham Date: Fri, 25 Oct 2019 14:46:07 -0400 Subject: [PATCH 22/22] Use ident instead of def_span in dead-code pass According to @estebank, def_span scans forward on the line until it finds a {, and if it can't find one, fallse back to the span for the whole item. This was apparently written before the identifier span was explicitly tracked on each node. This means that if an unused function signature spans multiple lines, the entire function (potentially hundreds of lines) gets flagged as dead code. This could, for example, cause IDEs to add error squiggly's to the whole function. By using the span from the ident instead, we narrow the scope of this in most cases. In a wider sense, it's probably safe to use ident.span instead of def_span in most locations throughout the whole code base, but since this is my first contribution, I kept it small. Some interesting points that came up while I was working on this: - I reorganized the tests a bit to bring some of the dead code ones all into the same location - A few tests were for things unrelated to dead code (like the path-lookahead for parens), so I added #![allow(dead_code)] and cleaned up the stderr file to reduce noise in the future - The same fix doesn't apply to const and static declarations. I tried adding these cases to the match expression, but that created a much wider change to tests and error messages, so I left it off until I could get some code review to validate the approach. --- src/librustc_passes/dead.rs | 2 +- .../lint-plugin-cmdline-allow.stderr | 4 +-- .../lint-tool-cmdline-allow.stderr | 4 +-- src/test/ui/lint/dead-code/basic.stderr | 4 +-- .../lint/dead-code/empty-unused-enum.stderr | 4 +-- .../ui/lint/dead-code/lint-dead-code-1.stderr | 28 +++++++++---------- .../ui/lint/dead-code/lint-dead-code-2.stderr | 12 ++++---- .../ui/lint/dead-code/lint-dead-code-3.stderr | 12 ++++---- .../ui/lint/dead-code/lint-dead-code-4.stderr | 4 +-- .../ui/lint/dead-code/lint-dead-code-5.stderr | 4 +-- src/test/ui/lint/dead-code/newline-span.rs | 19 +++++++++++++ .../ui/lint/dead-code/newline-span.stderr | 26 +++++++++++++++++ src/test/ui/lint/dead-code/unused-enum.stderr | 12 ++++---- .../ui/lint/dead-code/with-core-crate.stderr | 4 +-- src/test/ui/path-lookahead.rs | 8 +++--- src/test/ui/path-lookahead.stderr | 24 ++-------------- .../ui/span/macro-span-replacement.stderr | 7 ++--- ... => unused-warning-point-at-identifier.rs} | 4 +-- ...unused-warning-point-at-identifier.stderr} | 25 +++++++---------- .../ui/test-attrs/test-warns-dead-code.stderr | 4 +-- src/test/ui/thread-local-not-in-prelude.rs | 1 - 21 files changed, 114 insertions(+), 98 deletions(-) create mode 100644 src/test/ui/lint/dead-code/newline-span.rs create mode 100644 src/test/ui/lint/dead-code/newline-span.stderr rename src/test/ui/span/{unused-warning-point-at-signature.rs => unused-warning-point-at-identifier.rs} (84%) rename src/test/ui/span/{unused-warning-point-at-signature.stderr => unused-warning-point-at-identifier.stderr} (52%) diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index f2aef2c12c7df..9ad63f28a8e16 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -578,7 +578,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Trait(..) | - hir::ItemKind::Impl(..) => self.tcx.sess.source_map().def_span(item.span), + hir::ItemKind::Impl(..) => item.ident.span, _ => item.span, }; let participle = match item.kind { diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr index c6d198dc458a6..5ab3dfb24496f 100644 --- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr +++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr @@ -7,10 +7,10 @@ LL | #![plugin(lint_plugin_test)] = note: `#[warn(deprecated)]` on by default warning: function is never used: `lintme` - --> $DIR/lint-plugin-cmdline-allow.rs:10:1 + --> $DIR/lint-plugin-cmdline-allow.rs:10:4 | LL | fn lintme() { } - | ^^^^^^^^^^^ + | ^^^^^^ | note: lint level defined here --> $DIR/lint-plugin-cmdline-allow.rs:7:9 diff --git a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr index 239732521d59e..3a9fd7c2867f2 100644 --- a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr +++ b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr @@ -19,10 +19,10 @@ LL | fn lintme() {} = note: `#[warn(clippy::test_lint)]` on by default warning: function is never used: `lintme` - --> $DIR/lint-tool-cmdline-allow.rs:10:1 + --> $DIR/lint-tool-cmdline-allow.rs:10:4 | LL | fn lintme() {} - | ^^^^^^^^^^^ + | ^^^^^^ | note: lint level defined here --> $DIR/lint-tool-cmdline-allow.rs:7:9 diff --git a/src/test/ui/lint/dead-code/basic.stderr b/src/test/ui/lint/dead-code/basic.stderr index e5d1af12cf284..194398e5a07a5 100644 --- a/src/test/ui/lint/dead-code/basic.stderr +++ b/src/test/ui/lint/dead-code/basic.stderr @@ -1,8 +1,8 @@ error: function is never used: `foo` - --> $DIR/basic.rs:4:1 + --> $DIR/basic.rs:4:4 | LL | fn foo() { - | ^^^^^^^^ + | ^^^ | note: lint level defined here --> $DIR/basic.rs:1:9 diff --git a/src/test/ui/lint/dead-code/empty-unused-enum.stderr b/src/test/ui/lint/dead-code/empty-unused-enum.stderr index 17bbdfc71a260..44b0a8f613e27 100644 --- a/src/test/ui/lint/dead-code/empty-unused-enum.stderr +++ b/src/test/ui/lint/dead-code/empty-unused-enum.stderr @@ -1,8 +1,8 @@ error: enum is never used: `E` - --> $DIR/empty-unused-enum.rs:3:1 + --> $DIR/empty-unused-enum.rs:3:6 | LL | enum E {} - | ^^^^^^ + | ^ | note: lint level defined here --> $DIR/empty-unused-enum.rs:1:9 diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr index be96c697d9944..bac46a2e843cd 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr @@ -1,8 +1,8 @@ error: struct is never constructed: `Bar` - --> $DIR/lint-dead-code-1.rs:12:5 + --> $DIR/lint-dead-code-1.rs:12:16 | LL | pub struct Bar; - | ^^^^^^^^^^^^^^^ + | ^^^ | note: lint level defined here --> $DIR/lint-dead-code-1.rs:5:9 @@ -23,16 +23,16 @@ LL | const priv_const: isize = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct is never constructed: `PrivStruct` - --> $DIR/lint-dead-code-1.rs:35:1 + --> $DIR/lint-dead-code-1.rs:35:8 | LL | struct PrivStruct; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: enum is never used: `priv_enum` - --> $DIR/lint-dead-code-1.rs:64:1 + --> $DIR/lint-dead-code-1.rs:64:6 | LL | enum priv_enum { foo2, bar2 } - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^ error: variant is never constructed: `bar3` --> $DIR/lint-dead-code-1.rs:67:5 @@ -41,28 +41,28 @@ LL | bar3 | ^^^^ error: function is never used: `priv_fn` - --> $DIR/lint-dead-code-1.rs:88:1 + --> $DIR/lint-dead-code-1.rs:88:4 | LL | fn priv_fn() { - | ^^^^^^^^^^^^ + | ^^^^^^^ error: function is never used: `foo` - --> $DIR/lint-dead-code-1.rs:93:1 + --> $DIR/lint-dead-code-1.rs:93:4 | LL | fn foo() { - | ^^^^^^^^ + | ^^^ error: function is never used: `bar` - --> $DIR/lint-dead-code-1.rs:98:1 + --> $DIR/lint-dead-code-1.rs:98:4 | LL | fn bar() { - | ^^^^^^^^ + | ^^^ error: function is never used: `baz` - --> $DIR/lint-dead-code-1.rs:102:1 + --> $DIR/lint-dead-code-1.rs:102:4 | LL | fn baz() -> impl Copy { - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^ error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr index 1226f9823ac54..a578a76d9a075 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-2.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-2.stderr @@ -1,8 +1,8 @@ error: function is never used: `dead_fn` - --> $DIR/lint-dead-code-2.rs:22:1 + --> $DIR/lint-dead-code-2.rs:22:4 | LL | fn dead_fn() {} - | ^^^^^^^^^^^^ + | ^^^^^^^ | note: lint level defined here --> $DIR/lint-dead-code-2.rs:2:9 @@ -11,16 +11,16 @@ LL | #![deny(dead_code)] | ^^^^^^^^^ error: function is never used: `dead_fn2` - --> $DIR/lint-dead-code-2.rs:25:1 + --> $DIR/lint-dead-code-2.rs:25:4 | LL | fn dead_fn2() {} - | ^^^^^^^^^^^^^ + | ^^^^^^^^ error: function is never used: `main` - --> $DIR/lint-dead-code-2.rs:38:1 + --> $DIR/lint-dead-code-2.rs:38:4 | LL | fn main() { - | ^^^^^^^^^ + | ^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr index 2408da0af89ea..569196fffdd50 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -1,8 +1,8 @@ error: struct is never constructed: `Foo` - --> $DIR/lint-dead-code-3.rs:13:1 + --> $DIR/lint-dead-code-3.rs:13:8 | LL | struct Foo; - | ^^^^^^^^^^^ + | ^^^ | note: lint level defined here --> $DIR/lint-dead-code-3.rs:3:9 @@ -17,16 +17,16 @@ LL | fn foo(&self) { | ^^^^^^^^^^^^^ error: function is never used: `bar` - --> $DIR/lint-dead-code-3.rs:20:1 + --> $DIR/lint-dead-code-3.rs:20:4 | LL | fn bar() { - | ^^^^^^^^ + | ^^^ error: enum is never used: `c_void` - --> $DIR/lint-dead-code-3.rs:59:1 + --> $DIR/lint-dead-code-3.rs:59:6 | LL | enum c_void {} - | ^^^^^^^^^^^ + | ^^^^^^ error: foreign function is never used: `free` --> $DIR/lint-dead-code-3.rs:61:5 diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr index b7ceee99998d7..8eaf789f8f793 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr @@ -27,10 +27,10 @@ LL | | }, | |_____^ error: enum is never used: `ABC` - --> $DIR/lint-dead-code-4.rs:24:1 + --> $DIR/lint-dead-code-4.rs:24:6 | LL | enum ABC { - | ^^^^^^^^ + | ^^^ error: variant is never constructed: `I` --> $DIR/lint-dead-code-4.rs:36:5 diff --git a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr index 740cfde2c069f..9670d8e7a32e3 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr @@ -23,10 +23,10 @@ LL | Variant6(isize), | ^^^^^^^^^^^^^^^ error: enum is never used: `Enum3` - --> $DIR/lint-dead-code-5.rs:18:1 + --> $DIR/lint-dead-code-5.rs:18:6 | LL | enum Enum3 { - | ^^^^^^^^^^ + | ^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/dead-code/newline-span.rs b/src/test/ui/lint/dead-code/newline-span.rs new file mode 100644 index 0000000000000..a4342056419d7 --- /dev/null +++ b/src/test/ui/lint/dead-code/newline-span.rs @@ -0,0 +1,19 @@ +#![deny(dead_code)] + +fn unused() { //~ error: function is never used: + println!("blah"); +} + +fn unused2(var: i32) { //~ error: function is never used: + println!("foo {}", var); +} + +fn unused3( //~ error: function is never used: + var: i32, +) { + println!("bar {}", var); +} + +fn main() { + println!("Hello world!"); +} diff --git a/src/test/ui/lint/dead-code/newline-span.stderr b/src/test/ui/lint/dead-code/newline-span.stderr new file mode 100644 index 0000000000000..c5d0d60506744 --- /dev/null +++ b/src/test/ui/lint/dead-code/newline-span.stderr @@ -0,0 +1,26 @@ +error: function is never used: `unused` + --> $DIR/newline-span.rs:3:4 + | +LL | fn unused() { + | ^^^^^^ + | +note: lint level defined here + --> $DIR/newline-span.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: function is never used: `unused2` + --> $DIR/newline-span.rs:7:4 + | +LL | fn unused2(var: i32) { + | ^^^^^^^ + +error: function is never used: `unused3` + --> $DIR/newline-span.rs:11:4 + | +LL | fn unused3( + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/lint/dead-code/unused-enum.stderr b/src/test/ui/lint/dead-code/unused-enum.stderr index 682dfcf588182..142c2ccb99b05 100644 --- a/src/test/ui/lint/dead-code/unused-enum.stderr +++ b/src/test/ui/lint/dead-code/unused-enum.stderr @@ -1,8 +1,8 @@ error: struct is never constructed: `F` - --> $DIR/unused-enum.rs:3:1 + --> $DIR/unused-enum.rs:3:8 | LL | struct F; - | ^^^^^^^^^ + | ^ | note: lint level defined here --> $DIR/unused-enum.rs:1:9 @@ -12,16 +12,16 @@ LL | #![deny(unused)] = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` error: struct is never constructed: `B` - --> $DIR/unused-enum.rs:4:1 + --> $DIR/unused-enum.rs:4:8 | LL | struct B; - | ^^^^^^^^^ + | ^ error: enum is never used: `E` - --> $DIR/unused-enum.rs:6:1 + --> $DIR/unused-enum.rs:6:6 | LL | enum E { - | ^^^^^^ + | ^ error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/dead-code/with-core-crate.stderr b/src/test/ui/lint/dead-code/with-core-crate.stderr index 30caac3cd0148..0b6ab67d9bfa5 100644 --- a/src/test/ui/lint/dead-code/with-core-crate.stderr +++ b/src/test/ui/lint/dead-code/with-core-crate.stderr @@ -1,8 +1,8 @@ error: function is never used: `foo` - --> $DIR/with-core-crate.rs:7:1 + --> $DIR/with-core-crate.rs:7:4 | LL | fn foo() { - | ^^^^^^^^ + | ^^^ | note: lint level defined here --> $DIR/with-core-crate.rs:1:9 diff --git a/src/test/ui/path-lookahead.rs b/src/test/ui/path-lookahead.rs index fd7509a623e31..86bcb08de404e 100644 --- a/src/test/ui/path-lookahead.rs +++ b/src/test/ui/path-lookahead.rs @@ -1,14 +1,14 @@ // run-pass - -#![warn(unused)] +#![allow(dead_code)] +#![warn(unused_parens)] // Parser test for #37765 -fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` +fn with_parens(arg: T) -> String { return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value } -fn no_parens(arg: T) -> String { //~WARN function is never used: `no_parens` +fn no_parens(arg: T) -> String { return ::to_string(&arg); } diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr index 197848e428a25..caf9e8303ea37 100644 --- a/src/test/ui/path-lookahead.stderr +++ b/src/test/ui/path-lookahead.stderr @@ -7,26 +7,6 @@ LL | return (::to_string(&arg)); note: lint level defined here --> $DIR/path-lookahead.rs:3:9 | -LL | #![warn(unused)] - | ^^^^^^ - = note: `#[warn(unused_parens)]` implied by `#[warn(unused)]` - -warning: function is never used: `with_parens` - --> $DIR/path-lookahead.rs:7:1 - | -LL | fn with_parens(arg: T) -> String { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: lint level defined here - --> $DIR/path-lookahead.rs:3:9 - | -LL | #![warn(unused)] - | ^^^^^^ - = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` - -warning: function is never used: `no_parens` - --> $DIR/path-lookahead.rs:11:1 - | -LL | fn no_parens(arg: T) -> String { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![warn(unused_parens)] + | ^^^^^^^^^^^^^ diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr index 8b65e798b6ef5..439aedb4da4d2 100644 --- a/src/test/ui/span/macro-span-replacement.stderr +++ b/src/test/ui/span/macro-span-replacement.stderr @@ -1,11 +1,8 @@ warning: struct is never constructed: `S` - --> $DIR/macro-span-replacement.rs:7:14 + --> $DIR/macro-span-replacement.rs:7:12 | LL | $b $a; - | ^ -... -LL | m!(S struct); - | ------------- in this macro invocation + | ^^ | note: lint level defined here --> $DIR/macro-span-replacement.rs:3:9 diff --git a/src/test/ui/span/unused-warning-point-at-signature.rs b/src/test/ui/span/unused-warning-point-at-identifier.rs similarity index 84% rename from src/test/ui/span/unused-warning-point-at-signature.rs rename to src/test/ui/span/unused-warning-point-at-identifier.rs index 3af272a012eb2..d4d5bc1cbc8f1 100644 --- a/src/test/ui/span/unused-warning-point-at-signature.rs +++ b/src/test/ui/span/unused-warning-point-at-identifier.rs @@ -20,8 +20,8 @@ fn func() -> usize { //~ WARN function is never used 3 } -fn //~ WARN function is never used -func_complete_span() +fn +func_complete_span() //~ WARN function is never used -> usize { 3 diff --git a/src/test/ui/span/unused-warning-point-at-signature.stderr b/src/test/ui/span/unused-warning-point-at-identifier.stderr similarity index 52% rename from src/test/ui/span/unused-warning-point-at-signature.stderr rename to src/test/ui/span/unused-warning-point-at-identifier.stderr index 83e2ec1987b47..a4715d4adeb88 100644 --- a/src/test/ui/span/unused-warning-point-at-signature.stderr +++ b/src/test/ui/span/unused-warning-point-at-identifier.stderr @@ -1,36 +1,31 @@ warning: enum is never used: `Enum` - --> $DIR/unused-warning-point-at-signature.rs:5:1 + --> $DIR/unused-warning-point-at-identifier.rs:5:6 | LL | enum Enum { - | ^^^^^^^^^ + | ^^^^ | note: lint level defined here - --> $DIR/unused-warning-point-at-signature.rs:3:9 + --> $DIR/unused-warning-point-at-identifier.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` warning: struct is never constructed: `Struct` - --> $DIR/unused-warning-point-at-signature.rs:12:1 + --> $DIR/unused-warning-point-at-identifier.rs:12:8 | LL | struct Struct { - | ^^^^^^^^^^^^^ + | ^^^^^^ warning: function is never used: `func` - --> $DIR/unused-warning-point-at-signature.rs:19:1 + --> $DIR/unused-warning-point-at-identifier.rs:19:4 | LL | fn func() -> usize { - | ^^^^^^^^^^^^^^^^^^ + | ^^^^ warning: function is never used: `func_complete_span` - --> $DIR/unused-warning-point-at-signature.rs:23:1 + --> $DIR/unused-warning-point-at-identifier.rs:24:1 | -LL | / fn -LL | | func_complete_span() -LL | | -> usize -LL | | { -LL | | 3 -LL | | } - | |_^ +LL | func_complete_span() + | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/test-attrs/test-warns-dead-code.stderr b/src/test/ui/test-attrs/test-warns-dead-code.stderr index 62e99225dd902..cb118cdb4103c 100644 --- a/src/test/ui/test-attrs/test-warns-dead-code.stderr +++ b/src/test/ui/test-attrs/test-warns-dead-code.stderr @@ -1,8 +1,8 @@ error: function is never used: `dead` - --> $DIR/test-warns-dead-code.rs:5:1 + --> $DIR/test-warns-dead-code.rs:5:4 | LL | fn dead() {} - | ^^^^^^^^^ + | ^^^^ | note: lint level defined here --> $DIR/test-warns-dead-code.rs:3:9 diff --git a/src/test/ui/thread-local-not-in-prelude.rs b/src/test/ui/thread-local-not-in-prelude.rs index 039749826256f..e5ed09c600bf9 100644 --- a/src/test/ui/thread-local-not-in-prelude.rs +++ b/src/test/ui/thread-local-not-in-prelude.rs @@ -1,5 +1,4 @@ // run-pass - #![no_std] extern crate std;