Auto merge of #72575 - Dylan-DPC:rollup-zo679hv, r=Dylan-DPC
Rollup of 4 pull requests Successful merges: - #72153 (exhaustively check `ty::Kind` during structural match checking) - #72308 (Emit a better diagnostic when function actually has a 'self' parameter) - #72560 (Enable `glacier` command via triagebot) - #72567 (Clean up E0608 explanation) Failed merges: r? @ghost
This commit is contained in:
commit
f93bb2a50b
12 changed files with 173 additions and 11 deletions
|
@ -1,4 +1,4 @@
|
|||
An attempt to index into a type which doesn't implement the `std::ops::Index`
|
||||
An attempt to use index on a type which doesn't implement the `std::ops::Index`
|
||||
trait was performed.
|
||||
|
||||
Erroneous code example:
|
||||
|
|
|
@ -124,8 +124,20 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
traits::NonStructuralMatchTy::Dynamic => {
|
||||
"trait objects cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Opaque => {
|
||||
"opaque types cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Generator => {
|
||||
"generators cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Param => {
|
||||
bug!("use of constant whose type is a parameter inside a pattern")
|
||||
bug!("use of a constant whose type is a parameter inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTy::Projection => {
|
||||
bug!("use of a constant whose type is a projection inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTy::Foreign => {
|
||||
bug!("use of a value of a foreign type inside a pattern")
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -347,7 +347,7 @@ struct DiagnosticMetadata<'ast> {
|
|||
currently_processing_generics: bool,
|
||||
|
||||
/// The current enclosing function (used for better errors).
|
||||
current_function: Option<Span>,
|
||||
current_function: Option<(FnKind<'ast>, Span)>,
|
||||
|
||||
/// A list of labels as of yet unused. Labels will be removed from this map when
|
||||
/// they are used (in a `break` or `continue` statement)
|
||||
|
@ -466,7 +466,8 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||
FnKind::Fn(FnCtxt::Free | FnCtxt::Foreign, ..) => FnItemRibKind,
|
||||
FnKind::Fn(FnCtxt::Assoc(_), ..) | FnKind::Closure(..) => NormalRibKind,
|
||||
};
|
||||
let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some(sp));
|
||||
let previous_value =
|
||||
replace(&mut self.diagnostic_metadata.current_function, Some((fn_kind, sp)));
|
||||
debug!("(resolving function) entering function");
|
||||
let declaration = fn_kind.decl();
|
||||
|
||||
|
|
|
@ -195,8 +195,15 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
|
|||
_ => "`self` value is a keyword only available in methods with a `self` parameter"
|
||||
.to_string(),
|
||||
});
|
||||
if let Some(span) = &self.diagnostic_metadata.current_function {
|
||||
err.span_label(*span, "this function doesn't have a `self` parameter");
|
||||
if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function {
|
||||
// The current function has a `self' parameter, but we were unable to resolve
|
||||
// a reference to `self`. This can only happen if the `self` identifier we
|
||||
// are resolving came from a different hygiene context.
|
||||
if fn_kind.decl().inputs.get(0).map(|p| p.is_self()).unwrap_or(false) {
|
||||
err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
|
||||
} else {
|
||||
err.span_label(*span, "this function doesn't have a `self` parameter");
|
||||
}
|
||||
}
|
||||
return (err, Vec::new());
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ pub enum NonStructuralMatchTy<'tcx> {
|
|||
Adt(&'tcx AdtDef),
|
||||
Param,
|
||||
Dynamic,
|
||||
Foreign,
|
||||
Opaque,
|
||||
Generator,
|
||||
Projection,
|
||||
}
|
||||
|
||||
/// This method traverses the structure of `ty`, trying to find an
|
||||
|
@ -143,6 +147,22 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
|||
self.found = Some(NonStructuralMatchTy::Dynamic);
|
||||
return true; // Stop visiting.
|
||||
}
|
||||
ty::Foreign(_) => {
|
||||
self.found = Some(NonStructuralMatchTy::Foreign);
|
||||
return true; // Stop visiting.
|
||||
}
|
||||
ty::Opaque(..) => {
|
||||
self.found = Some(NonStructuralMatchTy::Opaque);
|
||||
return true; // Stop visiting.
|
||||
}
|
||||
ty::Projection(..) => {
|
||||
self.found = Some(NonStructuralMatchTy::Projection);
|
||||
return true; // Stop visiting.
|
||||
}
|
||||
ty::Generator(..) | ty::GeneratorWitness(..) => {
|
||||
self.found = Some(NonStructuralMatchTy::Generator);
|
||||
return true; // Stop visiting.
|
||||
}
|
||||
ty::RawPtr(..) => {
|
||||
// structural-match ignores substructure of
|
||||
// `*const _`/`*mut _`, so skip `super_visit_with`.
|
||||
|
@ -159,14 +179,14 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
|||
// structural equality on `T` does not recur into the raw
|
||||
// pointer. Therefore, one can still use `C` in a pattern.
|
||||
|
||||
// (But still tell caller to continue search.)
|
||||
// (But still tell the caller to continue search.)
|
||||
return false;
|
||||
}
|
||||
ty::FnDef(..) | ty::FnPtr(..) => {
|
||||
// types of formals and return in `fn(_) -> _` are also irrelevant;
|
||||
// Types of formals and return in `fn(_) -> _` are also irrelevant;
|
||||
// so we do not recur into them via `super_visit_with`
|
||||
//
|
||||
// (But still tell caller to continue search.)
|
||||
// (But still tell the caller to continue search.)
|
||||
return false;
|
||||
}
|
||||
ty::Array(_, n)
|
||||
|
@ -174,17 +194,40 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
|||
{
|
||||
// rust-lang/rust#62336: ignore type of contents
|
||||
// for empty array.
|
||||
//
|
||||
// (But still tell the caller to continue search.)
|
||||
return false;
|
||||
}
|
||||
_ => {
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
|
||||
// These primitive types are always structural match.
|
||||
//
|
||||
// `Never` is kind of special here, but as it is not inhabitable, this should be fine.
|
||||
//
|
||||
// (But still tell the caller to continue search.)
|
||||
return false;
|
||||
}
|
||||
|
||||
ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
|
||||
// First check all contained types and then tell the caller to continue searching.
|
||||
ty.super_visit_with(self);
|
||||
return false;
|
||||
}
|
||||
ty::Closure(..) | ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
|
||||
bug!("unexpected type during structural-match checking: {:?}", ty);
|
||||
}
|
||||
ty::Error => {
|
||||
self.tcx().sess.delay_span_bug(self.span, "ty::Error in structural-match check");
|
||||
// We still want to check other types after encountering an error,
|
||||
// as this may still emit relevant errors.
|
||||
//
|
||||
// So we continue searching here.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if !self.seen.insert(adt_def.did) {
|
||||
debug!("Search already seen adt_def: {:?}", adt_def);
|
||||
// let caller continue its search
|
||||
// Let caller continue its search.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
23
src/test/ui/hygiene/missing-self-diag.rs
Normal file
23
src/test/ui/hygiene/missing-self-diag.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Regression test for issue #66898
|
||||
// Tests that we don't emit a nonsensical error message
|
||||
// when a macro invocation tries to access `self` from a function
|
||||
// that has a 'self' parameter
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
macro_rules! call_bar {
|
||||
() => {
|
||||
self.bar(); //~ ERROR expected value
|
||||
}
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
pub fn foo(&self) {
|
||||
call_bar!();
|
||||
}
|
||||
|
||||
pub fn bar(&self) {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
17
src/test/ui/hygiene/missing-self-diag.stderr
Normal file
17
src/test/ui/hygiene/missing-self-diag.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
error[E0424]: expected value, found module `self`
|
||||
--> $DIR/missing-self-diag.rs:10:9
|
||||
|
|
||||
LL | self.bar();
|
||||
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
|
||||
...
|
||||
LL | / pub fn foo(&self) {
|
||||
LL | | call_bar!();
|
||||
| | ------------ in this macro invocation
|
||||
LL | | }
|
||||
| |_____- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0424`.
|
|
@ -0,0 +1,20 @@
|
|||
#![feature(const_fn, type_alias_impl_trait)]
|
||||
|
||||
type Bar = impl Send;
|
||||
|
||||
// While i32 is structural-match, we do not want to leak this information.
|
||||
// (See https://github.com/rust-lang/rust/issues/72156)
|
||||
const fn leak_free() -> Bar {
|
||||
7i32
|
||||
}
|
||||
const LEAK_FREE: Bar = leak_free();
|
||||
|
||||
fn leak_free_test() {
|
||||
match todo!() {
|
||||
LEAK_FREE => (),
|
||||
//~^ opaque types cannot be used in patterns
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
|
@ -0,0 +1,8 @@
|
|||
error: opaque types cannot be used in patterns
|
||||
--> $DIR/structural-match-no-leak.rs:14:9
|
||||
|
|
||||
LL | LEAK_FREE => (),
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
21
src/test/ui/type-alias-impl-trait/structural-match.rs
Normal file
21
src/test/ui/type-alias-impl-trait/structural-match.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
#![feature(const_fn, type_alias_impl_trait)]
|
||||
|
||||
type Foo = impl Send;
|
||||
|
||||
// This is not structural-match
|
||||
struct A;
|
||||
|
||||
const fn value() -> Foo {
|
||||
A
|
||||
}
|
||||
const VALUE: Foo = value();
|
||||
|
||||
fn test() {
|
||||
match todo!() {
|
||||
VALUE => (),
|
||||
//~^ opaque types cannot be used in patterns
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
|
@ -0,0 +1,8 @@
|
|||
error: opaque types cannot be used in patterns
|
||||
--> $DIR/structural-match.rs:15:9
|
||||
|
|
||||
LL | VALUE => (),
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -10,6 +10,8 @@ allow-unauthenticated = [
|
|||
|
||||
[assign]
|
||||
|
||||
[glacier]
|
||||
|
||||
[ping.icebreakers-llvm]
|
||||
alias = ["llvm", "llvms"]
|
||||
message = """\
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue