Skip to content

Commit beb547e

Browse files
committed
Report a specialized error when a 'static obligation comes from an impl dyn Trait
```text error: lifetime may not live long enough --> $DIR/static-impl-obligation.rs:8:27 | LL | fn bar<'a>(x: &'a &'a u32) { | -- lifetime `'a` defined here LL | let y: &dyn Foo = x; | ^ cast requires that `'a` must outlive `'static` LL | y.hello(); | --------- calling this method introduces a `'static` lifetime requirement | help: relax the implicit `'static` bound on the impl | LL | impl dyn Foo + '_ { | ++++ ``` ```text error: lifetime may not live long enough --> $DIR/static-impl-obligation.rs:173:27 | LL | fn bar<'a>(x: &'a &'a u32) { | -- lifetime `'a` defined here LL | let y: &dyn Foo = x; | ^ cast requires that `'a` must outlive `'static` LL | y.hello(); | --------- calling this method introduces a `'static` lifetime requirement | note: the `impl` on `(dyn p::Foo + 'static)` has `'static` lifetime requirements --> $DIR/static-impl-obligation.rs:169:20 | LL | impl dyn Foo + 'static where Self: 'static { | ^^^^^^^ ^^^^^^^ LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ ```
1 parent 8a49772 commit beb547e

File tree

19 files changed

+835
-73
lines changed

19 files changed

+835
-73
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3553,6 +3553,7 @@ dependencies = [
35533553
"either",
35543554
"itertools",
35553555
"polonius-engine",
3556+
"rustc_ast",
35563557
"rustc_data_structures",
35573558
"rustc_errors",
35583559
"rustc_fluent_macro",

compiler/rustc_borrowck/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ edition = "2021"
88
either = "1.5.0"
99
itertools = "0.11"
1010
polonius-engine = "0.13.0"
11+
rustc_ast = { path = "../rustc_ast" }
1112
rustc_data_structures = { path = "../rustc_data_structures" }
1213
rustc_errors = { path = "../rustc_errors" }
1314
rustc_fluent_macro = { path = "../rustc_fluent_macro" }

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+262-44
Large diffs are not rendered by default.

compiler/rustc_borrowck/src/region_infer/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2051,6 +2051,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
20512051
CRATE_DEF_ID.to_def_id(),
20522052
predicate_span,
20532053
))
2054+
} else if let ConstraintCategory::CallArgument(Some(fn_def)) = constraint.category {
2055+
Some(ObligationCauseCode::MethodCallConstraint(fn_def, constraint.span))
20542056
} else {
20552057
None
20562058
}

compiler/rustc_borrowck/src/type_check/canonical.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
100100
locations: Locations,
101101
) {
102102
for (predicate, span) in instantiated_predicates {
103-
debug!(?predicate);
103+
debug!(?span, ?predicate);
104104
let category = ConstraintCategory::Predicate(span);
105105
let predicate = self.normalize_with_category(predicate, locations, category);
106106
self.prove_predicate(predicate, locations, category);

compiler/rustc_borrowck/src/type_check/constraint_conversion.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Const
88
use rustc_middle::traits::query::NoSolution;
99
use rustc_middle::traits::ObligationCause;
1010
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
11-
use rustc_span::{Span, DUMMY_SP};
11+
use rustc_span::Span;
1212
use rustc_trait_selection::solve::deeply_normalize;
1313
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
1414
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@@ -183,7 +183,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
183183

184184
// we don't actually use this for anything, but
185185
// the `TypeOutlives` code needs an origin.
186-
let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
186+
let origin = infer::RelateParamBound(self.span, t1, None);
187187

188188
TypeOutlives::new(
189189
&mut *self,

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_middle::mir::ConstraintCategory;
1010
use rustc_middle::traits::query::OutlivesBound;
1111
use rustc_middle::traits::ObligationCause;
1212
use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
13-
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
13+
use rustc_span::{ErrorGuaranteed, Span};
1414
use rustc_trait_selection::solve::deeply_normalize;
1515
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
1616
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
@@ -269,7 +269,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
269269
debug!("build: input_or_output={:?}", ty);
270270
// We add implied bounds from both the unnormalized and normalized ty.
271271
// See issue #87748
272-
let constraints_unnorm = self.add_implied_bounds(ty);
272+
let constraints_unnorm = self.add_implied_bounds(ty, span);
273273
if let Some(c) = constraints_unnorm {
274274
constraints.push(c)
275275
}
@@ -299,7 +299,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
299299
// ```
300300
// Both &Self::Bar and &() are WF
301301
if ty != norm_ty {
302-
let constraints_norm = self.add_implied_bounds(norm_ty);
302+
let constraints_norm = self.add_implied_bounds(norm_ty, span);
303303
if let Some(c) = constraints_norm {
304304
constraints.push(c)
305305
}
@@ -323,7 +323,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
323323

324324
// We currently add implied bounds from the normalized ty only.
325325
// This is more conservative and matches wfcheck behavior.
326-
let c = self.add_implied_bounds(norm_ty);
326+
let c = self.add_implied_bounds(norm_ty, span);
327327
constraints.extend(c);
328328
}
329329
}
@@ -361,11 +361,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
361361
/// the same time, compute and add any implied bounds that come
362362
/// from this local.
363363
#[instrument(level = "debug", skip(self))]
364-
fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<&'tcx QueryRegionConstraints<'tcx>> {
364+
fn add_implied_bounds(
365+
&mut self,
366+
ty: Ty<'tcx>,
367+
span: Span,
368+
) -> Option<&'tcx QueryRegionConstraints<'tcx>> {
365369
let TypeOpOutput { output: bounds, constraints, .. } = self
366370
.param_env
367371
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
368-
.fully_perform(self.infcx, DUMMY_SP)
372+
.fully_perform(self.infcx, span)
369373
.map_err(|_: ErrorGuaranteed| debug!("failed to compute implied bounds {:?}", ty))
370374
.ok()?;
371375
debug!(?bounds, ?constraints);

compiler/rustc_borrowck/src/type_check/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use rustc_mir_dataflow::points::DenseLocationMap;
3737
use rustc_span::def_id::CRATE_DEF_ID;
3838
use rustc_span::source_map::Spanned;
3939
use rustc_span::symbol::sym;
40-
use rustc_span::{Span, DUMMY_SP};
40+
use rustc_span::Span;
4141
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
4242
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
4343
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
@@ -1014,7 +1014,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10141014
) -> Self {
10151015
let mut checker = Self {
10161016
infcx,
1017-
last_span: DUMMY_SP,
1017+
last_span: body.span,
10181018
body,
10191019
user_type_annotations: &body.user_type_annotations,
10201020
param_env,
@@ -2766,7 +2766,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
27662766
self.param_env,
27672767
self.known_type_outlives_obligations,
27682768
locations,
2769-
DUMMY_SP, // irrelevant; will be overridden.
2769+
self.body.span, // irrelevant; will be overridden.
27702770
ConstraintCategory::Boring, // same as above.
27712771
self.borrowck_context.constraints,
27722772
)

compiler/rustc_hir_analysis/src/collect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1630,7 +1630,7 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>(
16301630
#[instrument(level = "debug", skip(tcx))]
16311631
fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
16321632
let mut result = tcx.explicit_predicates_of(def_id);
1633-
debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result,);
1633+
debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result);
16341634
let inferred_outlives = tcx.inferred_outlives_of(def_id);
16351635
if !inferred_outlives.is_empty() {
16361636
debug!(

compiler/rustc_infer/src/infer/canonical/query_response.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ impl<'tcx> InferCtxt<'tcx> {
405405
/// will instantiate fresh inference variables for each canonical
406406
/// variable instead. Therefore, the result of this method must be
407407
/// properly unified
408-
#[instrument(level = "debug", skip(self, cause, param_env))]
408+
#[instrument(level = "debug", skip(self, param_env))]
409409
fn query_response_instantiation_guess<R>(
410410
&self,
411411
cause: &ObligationCause<'tcx>,

compiler/rustc_middle/src/traits/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,9 @@ pub enum ObligationCauseCode<'tcx> {
451451

452452
/// Obligations emitted during the normalization of a weak type alias.
453453
TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId),
454+
455+
/// During borrowck we've found a method call that could have introduced a lifetime requirement.
456+
MethodCallConstraint(Ty<'tcx>, Span),
454457
}
455458

456459
/// Whether a value can be extracted into a const.

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2683,6 +2683,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
26832683
| ObligationCauseCode::MethodReceiver
26842684
| ObligationCauseCode::ReturnNoExpression
26852685
| ObligationCauseCode::UnifyReceiver(..)
2686+
| ObligationCauseCode::MethodCallConstraint(..)
26862687
| ObligationCauseCode::MiscObligation
26872688
| ObligationCauseCode::WellFormed(..)
26882689
| ObligationCauseCode::MatchImpl(..)

compiler/rustc_trait_selection/src/traits/outlives_bounds.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ fn implied_outlives_bounds<'a, 'tcx>(
6262
};
6363

6464
let mut constraints = QueryRegionConstraints::default();
65+
let span = infcx.tcx.def_span(body_id);
6566
let Ok(InferOk { value: mut bounds, obligations }) = infcx
6667
.instantiate_nll_query_response_and_region_obligations(
67-
&ObligationCause::dummy(),
68+
&ObligationCause::dummy_with_span(span),
6869
param_env,
6970
&canonical_var_values,
7071
canonical_result,
@@ -80,8 +81,6 @@ fn implied_outlives_bounds<'a, 'tcx>(
8081
bounds.retain(|bound| !bound.has_placeholders());
8182

8283
if !constraints.is_empty() {
83-
let span = infcx.tcx.def_span(body_id);
84-
8584
debug!(?constraints);
8685
if !constraints.member_constraints.is_empty() {
8786
span_bug!(span, "{:#?}", constraints.member_constraints);
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ImpliedOutlivesBounds { ty: &'?2 mut StateContext<'?3, usize> } }
2+
--> $DIR/issue-80409.rs:48:30
23
|
3-
= query stack during panic:
4+
LL | builder.state().on_entry(|_| {});
5+
| ^^^
6+
|
7+
note: delayed at /home/gh-estebank/rust/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs:164:29 - disabled backtrace
8+
--> $DIR/issue-80409.rs:48:30
9+
|
10+
LL | builder.state().on_entry(|_| {});
11+
| ^^^
12+
13+
query stack during panic:
414
end of query stack
515
error: aborting due to 1 previous error
616

0 commit comments

Comments
 (0)