Manually register some bounds for a better span
This commit is contained in:
parent
e4c1a0016c
commit
97dfe8b871
@ -8,7 +8,7 @@
|
|||||||
use rustc_hir::def::{CtorKind, DefKind};
|
use rustc_hir::def::{CtorKind, DefKind};
|
||||||
use rustc_hir::{Node, intravisit};
|
use rustc_hir::{Node, intravisit};
|
||||||
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
|
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
|
||||||
use rustc_infer::traits::Obligation;
|
use rustc_infer::traits::{Obligation, ObligationCauseCode};
|
||||||
use rustc_lint_defs::builtin::{
|
use rustc_lint_defs::builtin::{
|
||||||
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
|
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
|
||||||
};
|
};
|
||||||
@ -267,7 +267,12 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
origin: hir::OpaqueTyOrigin<LocalDefId>,
|
origin: hir::OpaqueTyOrigin<LocalDefId>,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let span = span_of_opaque(tcx, def_id, origin).unwrap_or_else(|| tcx.def_span(def_id));
|
let (span, definition_def_id) =
|
||||||
|
if let Some((span, def_id)) = best_definition_site_of_opaque(tcx, def_id, origin) {
|
||||||
|
(span, Some(def_id))
|
||||||
|
} else {
|
||||||
|
(tcx.def_span(def_id), None)
|
||||||
|
};
|
||||||
|
|
||||||
let defining_use_anchor = match origin {
|
let defining_use_anchor = match origin {
|
||||||
hir::OpaqueTyOrigin::FnReturn { parent, .. }
|
hir::OpaqueTyOrigin::FnReturn { parent, .. }
|
||||||
@ -305,8 +310,32 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||||||
_ => re,
|
_ => re,
|
||||||
});
|
});
|
||||||
|
|
||||||
let misc_cause = traits::ObligationCause::misc(span, def_id);
|
// HACK: We eagerly instantiate some bounds to report better errors for them...
|
||||||
|
// This isn't necessary for correctness, since we register these bounds when
|
||||||
|
// equating the opaque below, but we should clean this up in the new solver.
|
||||||
|
for (predicate, pred_span) in
|
||||||
|
tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args)
|
||||||
|
{
|
||||||
|
let predicate = predicate.fold_with(&mut BottomUpFolder {
|
||||||
|
tcx,
|
||||||
|
ty_op: |ty| if ty == opaque_ty { hidden_ty } else { ty },
|
||||||
|
lt_op: |lt| lt,
|
||||||
|
ct_op: |ct| ct,
|
||||||
|
});
|
||||||
|
|
||||||
|
ocx.register_obligation(Obligation::new(
|
||||||
|
tcx,
|
||||||
|
ObligationCause::new(
|
||||||
|
span,
|
||||||
|
def_id,
|
||||||
|
ObligationCauseCode::OpaqueTypeBound(pred_span, definition_def_id),
|
||||||
|
),
|
||||||
|
param_env,
|
||||||
|
predicate,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let misc_cause = ObligationCause::misc(span, def_id);
|
||||||
// FIXME: We should just register the item bounds here, rather than equating.
|
// FIXME: We should just register the item bounds here, rather than equating.
|
||||||
match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
|
match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
@ -364,17 +393,17 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_of_opaque<'tcx>(
|
fn best_definition_site_of_opaque<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
opaque_def_id: LocalDefId,
|
opaque_def_id: LocalDefId,
|
||||||
origin: hir::OpaqueTyOrigin<LocalDefId>,
|
origin: hir::OpaqueTyOrigin<LocalDefId>,
|
||||||
) -> Option<Span> {
|
) -> Option<(Span, LocalDefId)> {
|
||||||
struct TaitConstraintLocator<'tcx> {
|
struct TaitConstraintLocator<'tcx> {
|
||||||
opaque_def_id: LocalDefId,
|
opaque_def_id: LocalDefId,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
}
|
}
|
||||||
impl<'tcx> TaitConstraintLocator<'tcx> {
|
impl<'tcx> TaitConstraintLocator<'tcx> {
|
||||||
fn check(&self, item_def_id: LocalDefId) -> ControlFlow<Span> {
|
fn check(&self, item_def_id: LocalDefId) -> ControlFlow<(Span, LocalDefId)> {
|
||||||
if !self.tcx.has_typeck_results(item_def_id) {
|
if !self.tcx.has_typeck_results(item_def_id) {
|
||||||
return ControlFlow::Continue(());
|
return ControlFlow::Continue(());
|
||||||
}
|
}
|
||||||
@ -382,7 +411,7 @@ fn check(&self, item_def_id: LocalDefId) -> ControlFlow<Span> {
|
|||||||
if let Some(hidden_ty) =
|
if let Some(hidden_ty) =
|
||||||
self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id)
|
self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id)
|
||||||
{
|
{
|
||||||
ControlFlow::Break(hidden_ty.span)
|
ControlFlow::Break((hidden_ty.span, item_def_id))
|
||||||
} else {
|
} else {
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
@ -390,7 +419,7 @@ fn check(&self, item_def_id: LocalDefId) -> ControlFlow<Span> {
|
|||||||
}
|
}
|
||||||
impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
|
impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
|
||||||
type NestedFilter = nested_filter::All;
|
type NestedFilter = nested_filter::All;
|
||||||
type Result = ControlFlow<Span>;
|
type Result = ControlFlow<(Span, LocalDefId)>;
|
||||||
fn nested_visit_map(&mut self) -> Self::Map {
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
self.tcx.hir()
|
self.tcx.hir()
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@ pub fn register_region_obligation_with_cause(
|
|||||||
infer::RelateParamBound(cause.span, sup_type, match cause.code().peel_derives() {
|
infer::RelateParamBound(cause.span, sup_type, match cause.code().peel_derives() {
|
||||||
ObligationCauseCode::WhereClause(_, span)
|
ObligationCauseCode::WhereClause(_, span)
|
||||||
| ObligationCauseCode::WhereClauseInExpr(_, span, ..)
|
| ObligationCauseCode::WhereClauseInExpr(_, span, ..)
|
||||||
|
| ObligationCauseCode::OpaqueTypeBound(span, _)
|
||||||
if !span.is_dummy() =>
|
if !span.is_dummy() =>
|
||||||
{
|
{
|
||||||
Some(*span)
|
Some(*span)
|
||||||
|
@ -193,6 +193,11 @@ pub enum ObligationCauseCode<'tcx> {
|
|||||||
/// The span corresponds to the clause.
|
/// The span corresponds to the clause.
|
||||||
WhereClause(DefId, Span),
|
WhereClause(DefId, Span),
|
||||||
|
|
||||||
|
/// Represents a bound for an opaque we are checking the well-formedness of.
|
||||||
|
/// The def-id corresponds to a specific definition site that we found the
|
||||||
|
/// hidden type from, if any.
|
||||||
|
OpaqueTypeBound(Span, Option<LocalDefId>),
|
||||||
|
|
||||||
/// Like `WhereClause`, but also identifies the expression
|
/// Like `WhereClause`, but also identifies the expression
|
||||||
/// which requires the `where` clause to be proven, and also
|
/// which requires the `where` clause to be proven, and also
|
||||||
/// identifies the index of the predicate in the `predicates_of`
|
/// identifies the index of the predicate in the `predicates_of`
|
||||||
|
@ -2953,6 +2953,22 @@ pub(super) fn note_obligation_cause_code<G: EmissionGuarantee, T>(
|
|||||||
// We hold the `DefId` of the item introducing the obligation, but displaying it
|
// We hold the `DefId` of the item introducing the obligation, but displaying it
|
||||||
// doesn't add user usable information. It always point at an associated item.
|
// doesn't add user usable information. It always point at an associated item.
|
||||||
}
|
}
|
||||||
|
ObligationCauseCode::OpaqueTypeBound(span, definition_def_id) => {
|
||||||
|
err.span_note(span, "required by a bound in an opaque type");
|
||||||
|
if let Some(definition_def_id) = definition_def_id
|
||||||
|
// If there are any stalled coroutine obligations, then this
|
||||||
|
// error may be due to that, and not because the body has more
|
||||||
|
// where-clauses.
|
||||||
|
&& self.tcx.typeck(definition_def_id).coroutine_stalled_predicates.is_empty()
|
||||||
|
{
|
||||||
|
// FIXME(compiler-errors): We could probably point to something
|
||||||
|
// specific here if we tried hard enough...
|
||||||
|
err.span_note(
|
||||||
|
tcx.def_span(definition_def_id),
|
||||||
|
"this definition site has more where clauses than the opaque type",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
ObligationCauseCode::Coercion { source, target } => {
|
ObligationCauseCode::Coercion { source, target } => {
|
||||||
let source =
|
let source =
|
||||||
tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file);
|
tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file);
|
||||||
|
@ -35,6 +35,11 @@ note: required because it's used within this `async` block
|
|||||||
|
|
|
|
||||||
LL | async move {
|
LL | async move {
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
note: required by a bound in an opaque type
|
||||||
|
--> $DIR/issue-70935-complex-spans.rs:15:37
|
||||||
|
|
|
||||||
|
LL | fn foo(x: NotSync) -> impl Future + Send {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
error[E0277]: `*mut ()` cannot be shared between threads safely
|
error[E0277]: `*mut ()` cannot be shared between threads safely
|
||||||
--> $DIR/issue-70935-complex-spans.rs:15:23
|
--> $DIR/issue-70935-complex-spans.rs:15:23
|
||||||
|
@ -4,6 +4,16 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
|
|||||||
LL | t
|
LL | t
|
||||||
| ^ the trait `Clone` is not implemented for `T`
|
| ^ the trait `Clone` is not implemented for `T`
|
||||||
|
|
|
|
||||||
|
note: required by a bound in an opaque type
|
||||||
|
--> $DIR/bounds-are-checked-2.rs:7:26
|
||||||
|
|
|
||||||
|
LL | pub type X<T> = impl Clone;
|
||||||
|
| ^^^^^
|
||||||
|
note: this definition site has more where clauses than the opaque type
|
||||||
|
--> $DIR/bounds-are-checked-2.rs:9:5
|
||||||
|
|
|
||||||
|
LL | fn f<T: Clone>(t: T) -> X<T> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider restricting type parameter `T`
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
|
||||||
LL | pub type X<T: std::clone::Clone> = impl Clone;
|
LL | pub type X<T: std::clone::Clone> = impl Clone;
|
||||||
|
@ -4,6 +4,16 @@ error[E0277]: `T` doesn't implement `Debug`
|
|||||||
LL | t
|
LL | t
|
||||||
| ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
| ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
||||||
|
|
|
|
||||||
|
note: required by a bound in an opaque type
|
||||||
|
--> $DIR/generic_duplicate_param_use2.rs:8:23
|
||||||
|
|
|
||||||
|
LL | type Two<T, U> = impl Debug;
|
||||||
|
| ^^^^^
|
||||||
|
note: this definition site has more where clauses than the opaque type
|
||||||
|
--> $DIR/generic_duplicate_param_use2.rs:10:1
|
||||||
|
|
|
||||||
|
LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider restricting type parameter `T`
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
|
||||||
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
|
LL | type Two<T: std::fmt::Debug, U> = impl Debug;
|
||||||
|
@ -4,6 +4,16 @@ error[E0277]: `U` doesn't implement `Debug`
|
|||||||
LL | u
|
LL | u
|
||||||
| ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
| ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
||||||
|
|
|
|
||||||
|
note: required by a bound in an opaque type
|
||||||
|
--> $DIR/generic_duplicate_param_use4.rs:8:23
|
||||||
|
|
|
||||||
|
LL | type Two<T, U> = impl Debug;
|
||||||
|
| ^^^^^
|
||||||
|
note: this definition site has more where clauses than the opaque type
|
||||||
|
--> $DIR/generic_duplicate_param_use4.rs:10:1
|
||||||
|
|
|
||||||
|
LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider restricting type parameter `U`
|
help: consider restricting type parameter `U`
|
||||||
|
|
|
|
||||||
LL | type Two<T, U: std::fmt::Debug> = impl Debug;
|
LL | type Two<T, U: std::fmt::Debug> = impl Debug;
|
||||||
|
@ -21,6 +21,20 @@ LL | impl<T: Proj<Assoc = i32> + Copy> Copy for Bar<T> {}
|
|||||||
| ----------- ^^^^ ^^^^^^
|
| ----------- ^^^^ ^^^^^^
|
||||||
| |
|
| |
|
||||||
| unsatisfied trait bound introduced here
|
| unsatisfied trait bound introduced here
|
||||||
|
note: required by a bound in an opaque type
|
||||||
|
--> $DIR/hidden_type_mismatch.rs:36:26
|
||||||
|
|
|
||||||
|
LL | pub type Tait = impl Copy + From<Bar<()>> + Into<Bar<()>>;
|
||||||
|
| ^^^^
|
||||||
|
note: this definition site has more where clauses than the opaque type
|
||||||
|
--> $DIR/hidden_type_mismatch.rs:37:5
|
||||||
|
|
|
||||||
|
LL | / pub fn define_tait() -> Tait
|
||||||
|
LL | | where
|
||||||
|
LL | | // this proves `Bar<()>: Copy`, but `define_tait` is
|
||||||
|
LL | | // now uncallable
|
||||||
|
LL | | (): Proj<Assoc = i32>,
|
||||||
|
| |______________________________^
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -5,8 +5,13 @@ LL | s
|
|||||||
| ^
|
| ^
|
||||||
| |
|
| |
|
||||||
| the parameter type `A` must be valid for the static lifetime...
|
| the parameter type `A` must be valid for the static lifetime...
|
||||||
| ...so that the type `A` will meet its required lifetime bounds
|
| ...so that the type `A` will meet its required lifetime bounds...
|
||||||
|
|
|
|
||||||
|
note: ...that is required by this bound
|
||||||
|
--> $DIR/implied_lifetime_wf_check4_static.rs:4:35
|
||||||
|
|
|
||||||
|
LL | pub type Ty<A> = impl Sized + 'static;
|
||||||
|
| ^^^^^^^
|
||||||
help: consider adding an explicit lifetime bound
|
help: consider adding an explicit lifetime bound
|
||||||
|
|
|
|
||||||
LL | pub type Ty<A: 'static> = impl Sized + 'static;
|
LL | pub type Ty<A: 'static> = impl Sized + 'static;
|
||||||
|
@ -4,6 +4,16 @@ error[E0277]: the trait bound `T: Default` is not satisfied
|
|||||||
LL | t
|
LL | t
|
||||||
| ^ the trait `Default` is not implemented for `T`
|
| ^ the trait `Default` is not implemented for `T`
|
||||||
|
|
|
|
||||||
|
note: required by a bound in an opaque type
|
||||||
|
--> $DIR/issue-52843.rs:3:20
|
||||||
|
|
|
||||||
|
LL | type Foo<T> = impl Default;
|
||||||
|
| ^^^^^^^
|
||||||
|
note: this definition site has more where clauses than the opaque type
|
||||||
|
--> $DIR/issue-52843.rs:6:1
|
||||||
|
|
|
||||||
|
LL | fn foo<T: Default>(t: T) -> Foo<T> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider restricting type parameter `T`
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
|
||||||
LL | type Foo<T: std::default::Default> = impl Default;
|
LL | type Foo<T: std::default::Default> = impl Default;
|
||||||
|
@ -4,11 +4,23 @@ error[E0277]: the trait bound `B: Bar` is not satisfied
|
|||||||
LL | MyBaz(bar)
|
LL | MyBaz(bar)
|
||||||
| ^^^^^^^^^^ the trait `Bar` is not implemented for `B`
|
| ^^^^^^^^^^ the trait `Bar` is not implemented for `B`
|
||||||
|
|
|
|
||||||
note: required by a bound in `MyBaz`
|
note: required for `MyBaz<B>` to implement `Baz`
|
||||||
--> $DIR/issue-90400-2.rs:29:17
|
--> $DIR/issue-90400-2.rs:30:14
|
||||||
|
|
|
|
||||||
LL | struct MyBaz<B: Bar>(B);
|
LL | impl<B: Bar> Baz for MyBaz<B> {
|
||||||
| ^^^ required by this bound in `MyBaz`
|
| --- ^^^ ^^^^^^^^
|
||||||
|
| |
|
||||||
|
| unsatisfied trait bound introduced here
|
||||||
|
note: required by a bound in an opaque type
|
||||||
|
--> $DIR/issue-90400-2.rs:22:26
|
||||||
|
|
|
||||||
|
LL | type FooFn<B> = impl Baz;
|
||||||
|
| ^^^
|
||||||
|
note: this definition site has more where clauses than the opaque type
|
||||||
|
--> $DIR/issue-90400-2.rs:24:5
|
||||||
|
|
|
||||||
|
LL | fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider restricting type parameter `B`
|
help: consider restricting type parameter `B`
|
||||||
|
|
|
|
||||||
LL | type FooFn<B: Bar> = impl Baz;
|
LL | type FooFn<B: Bar> = impl Baz;
|
||||||
|
@ -11,6 +11,16 @@ LL | impl<X: Trait> ProofForConversion<X> for () {
|
|||||||
| ----- ^^^^^^^^^^^^^^^^^^^^^ ^^
|
| ----- ^^^^^^^^^^^^^^^^^^^^^ ^^
|
||||||
| |
|
| |
|
||||||
| unsatisfied trait bound introduced here
|
| unsatisfied trait bound introduced here
|
||||||
|
note: required by a bound in an opaque type
|
||||||
|
--> $DIR/underconstrained_generic.rs:19:26
|
||||||
|
|
|
||||||
|
LL | type Converter<T> = impl ProofForConversion<T>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: this definition site has more where clauses than the opaque type
|
||||||
|
--> $DIR/underconstrained_generic.rs:21:1
|
||||||
|
|
|
||||||
|
LL | fn _defining_use<T: Trait>() -> Converter<T> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
help: consider restricting type parameter `T`
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
|
||||||
LL | type Converter<T: Trait> = impl ProofForConversion<T>;
|
LL | type Converter<T: Trait> = impl ProofForConversion<T>;
|
||||||
|
@ -5,8 +5,13 @@ LL | impl<'a, T> Trait<'a, T> for () {
|
|||||||
| -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
|
| -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
|
||||||
...
|
...
|
||||||
LL | req
|
LL | req
|
||||||
| ^^^ ...so that the type `&'a T` will meet its required lifetime bounds
|
| ^^^ ...so that the type `&'a T` will meet its required lifetime bounds...
|
||||||
|
|
|
|
||||||
|
note: ...that is required by this bound
|
||||||
|
--> $DIR/wf-in-associated-type.rs:38:36
|
||||||
|
|
|
||||||
|
LL | type Opaque = impl Sized + 'a;
|
||||||
|
| ^^
|
||||||
help: consider adding an explicit lifetime bound
|
help: consider adding an explicit lifetime bound
|
||||||
|
|
|
|
||||||
LL | impl<'a, T: 'a> Trait<'a, T> for () {
|
LL | impl<'a, T: 'a> Trait<'a, T> for () {
|
||||||
|
Loading…
Reference in New Issue
Block a user