Skip to content

Commit 4fc06ac

Browse files
committed
Arbitrary self types v2: diagnostics in resolution.
If we get past all the earlier stages of validation (in well-formedness checking and in probing) there's still a chance that resolving the self type will produce errors at the 'confirmation' stage. Add an extra note to those errors to make it clear that they were encountered while resolving the 'self' type. This is a fairly niche case and users may not encounter it often. It's arguably not worth the extra complexity required to produce this note. Opinions welcome.
1 parent eedc229 commit 4fc06ac

File tree

11 files changed

+85
-9
lines changed

11 files changed

+85
-9
lines changed

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_middle::ty::{
1818
};
1919
use rustc_span::Span;
2020
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
21+
use rustc_trait_selection::error_reporting::infer::TypeErrorRole;
2122
use rustc_trait_selection::error_reporting::infer::nice_region_error::NiceRegionError;
2223
use rustc_trait_selection::traits::ObligationCtxt;
2324
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
@@ -464,6 +465,7 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
464465
*trace,
465466
infcx.tcx.param_env(generic_param_scope),
466467
TypeError::RegionsPlaceholderMismatch,
468+
TypeErrorRole::Elsewhere,
467469
))
468470
} else {
469471
None

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_middle::ty::{
2222
use rustc_middle::{bug, span_bug};
2323
use rustc_span::Span;
2424
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
25+
use rustc_trait_selection::error_reporting::infer::TypeErrorRole;
2526
use rustc_trait_selection::infer::InferCtxtExt;
2627
use rustc_trait_selection::regions::InferCtxtRegionExt;
2728
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
@@ -639,6 +640,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
639640
}))),
640641
terr,
641642
false,
643+
TypeErrorRole::Elsewhere,
642644
);
643645
return Err(diag.emit());
644646
}
@@ -1060,6 +1062,7 @@ fn report_trait_method_mismatch<'tcx>(
10601062
}))),
10611063
terr,
10621064
false,
1065+
TypeErrorRole::Elsewhere,
10631066
);
10641067

10651068
diag.emit()
@@ -1852,6 +1855,7 @@ fn compare_const_predicate_entailment<'tcx>(
18521855
}))),
18531856
terr,
18541857
false,
1858+
TypeErrorRole::Elsewhere,
18551859
);
18561860
return Err(diag.emit());
18571861
};

compiler/rustc_hir_analysis/src/check/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ use rustc_span::def_id::CRATE_DEF_ID;
9292
use rustc_span::symbol::{Ident, kw, sym};
9393
use rustc_span::{BytePos, DUMMY_SP, Span, Symbol};
9494
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
95-
use rustc_trait_selection::error_reporting::infer::ObligationCauseExt as _;
95+
use rustc_trait_selection::error_reporting::infer::{ObligationCauseExt as _, TypeErrorRole};
9696
use rustc_trait_selection::error_reporting::traits::suggestions::ReturnsVisitor;
9797
use rustc_trait_selection::traits::ObligationCtxt;
9898
use tracing::debug;
@@ -651,6 +651,7 @@ pub fn check_function_signature<'tcx>(
651651
}))),
652652
err,
653653
false,
654+
TypeErrorRole::Elsewhere,
654655
);
655656
return Err(diag.emit());
656657
}

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ use rustc_middle::{bug, span_bug};
2424
use rustc_session::Session;
2525
use rustc_span::symbol::{Ident, kw};
2626
use rustc_span::{DUMMY_SP, Span, sym};
27-
use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
27+
use rustc_trait_selection::error_reporting::infer::{
28+
FailureCode, ObligationCauseExt, TypeErrorRole,
29+
};
2830
use rustc_trait_selection::infer::InferCtxtExt;
2931
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
3032
use tracing::debug;
@@ -830,6 +832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
830832
),
831833
self.param_env,
832834
terr,
835+
TypeErrorRole::Elsewhere,
833836
);
834837
err.span_label(
835838
full_call_span,
@@ -942,8 +945,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
942945
let trace =
943946
mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
944947
if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
945-
let mut err =
946-
self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *e);
948+
let mut err = self.err_ctxt().report_and_explain_type_error(
949+
trace,
950+
self.param_env,
951+
*e,
952+
TypeErrorRole::Elsewhere,
953+
);
947954
suggest_confusable(&mut err);
948955
reported = Some(err.emit());
949956
return false;
@@ -971,7 +978,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
971978
let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
972979
let (provided_ty, provided_arg_span) = provided_arg_tys[provided_idx];
973980
let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
974-
let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err);
981+
let mut err = self.err_ctxt().report_and_explain_type_error(
982+
trace,
983+
self.param_env,
984+
err,
985+
TypeErrorRole::Elsewhere,
986+
);
975987
self.emit_coerce_suggestions(
976988
&mut err,
977989
provided_args[provided_idx],
@@ -1148,6 +1160,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11481160
Some(self.param_env.and(trace.values)),
11491161
e,
11501162
true,
1163+
TypeErrorRole::Elsewhere,
11511164
);
11521165
}
11531166
}

compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
531531
Err(terr) => {
532532
if self.tcx.features().arbitrary_self_types() {
533533
self.err_ctxt()
534-
.report_mismatched_types(
534+
.report_mismatched_self_types(
535535
&cause,
536536
self.param_env,
537537
method_self_ty,

compiler/rustc_passes/src/check_attr.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use rustc_span::{BytePos, DUMMY_SP, Span};
3535
use rustc_target::abi::Size;
3636
use rustc_target::spec::abi::Abi;
3737
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
38+
use rustc_trait_selection::error_reporting::infer::TypeErrorRole;
3839
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
3940
use rustc_trait_selection::traits::ObligationCtxt;
4041
use tracing::debug;
@@ -2371,6 +2372,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
23712372
}))),
23722373
terr,
23732374
false,
2375+
TypeErrorRole::Elsewhere,
23742376
);
23752377
diag.emit();
23762378
self.abort.set(true);

compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@ pub mod nice_region_error;
9292
pub mod region;
9393
pub mod sub_relations;
9494

95+
/// A hint about where a type error occurred, for better diagnostics.
96+
#[derive(Debug, PartialEq)]
97+
pub enum TypeErrorRole {
98+
/// This type error occurred while resolving the "self" type of a method
99+
SelfType,
100+
/// This type error occurred in any other context.
101+
Elsewhere,
102+
}
103+
95104
/// Makes a valid string literal from a string by escaping special characters (" and \),
96105
/// unless they are already escaped.
97106
fn escape_literal(s: &str) -> String {
@@ -159,6 +168,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
159168
TypeTrace::types(cause, expected, actual),
160169
param_env,
161170
err,
171+
TypeErrorRole::Elsewhere,
172+
)
173+
}
174+
175+
pub fn report_mismatched_self_types(
176+
&self,
177+
cause: &ObligationCause<'tcx>,
178+
param_env: ty::ParamEnv<'tcx>,
179+
expected: Ty<'tcx>,
180+
actual: Ty<'tcx>,
181+
err: TypeError<'tcx>,
182+
) -> Diag<'a> {
183+
self.report_and_explain_type_error(
184+
TypeTrace::types(cause, expected, actual),
185+
param_env,
186+
err,
187+
TypeErrorRole::SelfType,
162188
)
163189
}
164190

@@ -174,6 +200,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
174200
TypeTrace::consts(cause, expected, actual),
175201
param_env,
176202
err,
203+
TypeErrorRole::Elsewhere,
177204
)
178205
}
179206

@@ -1376,6 +1403,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
13761403
mut values: Option<ty::ParamEnvAnd<'tcx, ValuePairs<'tcx>>>,
13771404
terr: TypeError<'tcx>,
13781405
prefer_label: bool,
1406+
role: TypeErrorRole,
13791407
) {
13801408
let span = cause.span;
13811409

@@ -1839,6 +1867,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18391867
}
18401868
}
18411869

1870+
if role == TypeErrorRole::SelfType {
1871+
diag.note("this error occurred while resolving the `self` type of this method call");
1872+
}
1873+
18421874
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
18431875
if let Some(exp_found) = exp_found
18441876
&& let exp_found = TypeError::Sorts(exp_found)
@@ -2026,8 +2058,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
20262058
trace: TypeTrace<'tcx>,
20272059
param_env: ty::ParamEnv<'tcx>,
20282060
terr: TypeError<'tcx>,
2061+
role: TypeErrorRole,
20292062
) -> Diag<'a> {
2030-
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
2063+
debug!(
2064+
"report_and_explain_type_error(trace={:?}, terr={:?}, role={:?})",
2065+
trace, terr, role
2066+
);
20312067

20322068
let span = trace.cause.span;
20332069
let failure_code = trace.cause.as_failure_code_diag(
@@ -2043,6 +2079,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
20432079
Some(param_env.and(trace.values)),
20442080
terr,
20452081
false,
2082+
role,
20462083
);
20472084
diag
20482085
}

compiler/rustc_trait_selection/src/error_reporting/infer/region.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol};
1717
use rustc_type_ir::Upcast as _;
1818
use tracing::{debug, instrument};
1919

20-
use super::ObligationCauseAsDiagArg;
2120
use super::nice_region_error::find_anon_type;
21+
use super::{ObligationCauseAsDiagArg, TypeErrorRole};
2222
use crate::error_reporting::TypeErrCtxt;
2323
use crate::error_reporting::infer::ObligationCauseExt;
2424
use crate::errors::{
@@ -299,6 +299,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
299299
trace,
300300
self.tcx.param_env(generic_param_scope),
301301
terr,
302+
TypeErrorRole::Elsewhere,
302303
);
303304
match (*sub, *sup) {
304305
(ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
@@ -654,6 +655,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
654655
trace,
655656
self.tcx.param_env(generic_param_scope),
656657
terr,
658+
TypeErrorRole::Elsewhere,
657659
);
658660
}
659661
_ => {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use super::{
3838
UnsatisfiedConst,
3939
};
4040
use crate::error_reporting::TypeErrCtxt;
41-
use crate::error_reporting::infer::TyCategory;
41+
use crate::error_reporting::infer::{TyCategory, TypeErrorRole};
4242
use crate::error_reporting::traits::report_dyn_incompatibility;
4343
use crate::errors::{
4444
AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
@@ -727,6 +727,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
727727
None,
728728
TypeError::Sorts(ty::error::ExpectedFound::new(expected_ty, ct_ty)),
729729
false,
730+
TypeErrorRole::Elsewhere
730731
);
731732
diag
732733
}
@@ -1455,6 +1456,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
14551456
}),
14561457
err,
14571458
false,
1459+
TypeErrorRole::Elsewhere,
14581460
);
14591461
self.note_obligation_cause(&mut diag, obligation);
14601462
diag.emit()
@@ -2741,6 +2743,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
27412743
TypeTrace::trait_refs(&cause, expected_trait_ref, found_trait_ref),
27422744
obligation.param_env,
27432745
terr,
2746+
TypeErrorRole::Elsewhere,
27442747
)
27452748
}
27462749

@@ -2832,6 +2835,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
28322835
TypeTrace::trait_refs(&obligation.cause, expected_trait_ref, found_trait_ref),
28332836
obligation.param_env,
28342837
ty::error::TypeError::Mismatch,
2838+
TypeErrorRole::Elsewhere,
28352839
));
28362840
}
28372841
if found.len() != expected.len() {

tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,16 @@ error[E0308]: mismatched types
3939
|
4040
LL | assert_eq!(foo.a::<&Foo>(), 2);
4141
| ^^^ expected `&Foo`, found `Foo`
42+
|
43+
= note: this error occurred while resolving the `self` type of this method call
4244

4345
error[E0308]: mismatched types
4446
--> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:53:16
4547
|
4648
LL | assert_eq!(foo.b::<&Foo>(), 1);
4749
| ^^^ expected `&Foo`, found `Foo`
50+
|
51+
= note: this error occurred while resolving the `self` type of this method call
4852

4953
error[E0308]: mismatched types
5054
--> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:60:16
@@ -54,6 +58,7 @@ LL | assert_eq!(smart_ptr.a::<&Foo>(), 2);
5458
|
5559
= note: expected reference `&Foo`
5660
found struct `SmartPtr<'_, Foo, >`
61+
= note: this error occurred while resolving the `self` type of this method call
5762

5863
error[E0308]: mismatched types
5964
--> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:62:16
@@ -63,6 +68,7 @@ LL | assert_eq!(smart_ptr.b::<&Foo>(), 1);
6368
|
6469
= note: expected reference `&Foo`
6570
found struct `SmartPtr<'_, Foo, >`
71+
= note: this error occurred while resolving the `self` type of this method call
6672

6773
error: aborting due to 8 previous errors
6874

0 commit comments

Comments
 (0)