Rollup merge of #70006 - petrochenkov:fresh, r=Centril

resolve: Fix two issues in fresh binding disambiguation

Prevent fresh bindings from shadowing ambiguity items.
Fixes https://github.com/rust-lang/rust/issues/46079

Correctly treat const generic parameters in fresh binding disambiguation.
Fixes https://github.com/rust-lang/rust/issues/68853
This commit is contained in:
Mazdak Farrokhzad 2020-03-15 15:40:10 +01:00 committed by GitHub
commit d986a706bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 123 additions and 24 deletions

View File

@ -87,6 +87,9 @@ impl PatCtxt<'_, '_> {
PatternError::AssocConstInPattern(span) => {
self.span_e0158(span, "associated consts cannot be referenced in patterns")
}
PatternError::ConstParamInPattern(span) => {
self.span_e0158(span, "const parameters cannot be referenced in patterns")
}
PatternError::FloatBug => {
// FIXME(#31407) this is only necessary because float parsing is buggy
::rustc::mir::interpret::struct_error(

View File

@ -31,6 +31,7 @@ use std::fmt;
#[derive(Clone, Debug)]
crate enum PatternError {
AssocConstInPattern(Span),
ConstParamInPattern(Span),
StaticInPattern(Span),
FloatBug,
NonConstPath(Span),
@ -727,7 +728,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
| Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
_ => {
self.errors.push(PatternError::NonConstPath(span));
let pattern_error = match res {
Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
_ => PatternError::NonConstPath(span),
};
self.errors.push(pattern_error);
PatKind::Wild
}
};

View File

@ -1517,9 +1517,17 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ident: Ident,
has_sub: bool,
) -> Option<Res> {
let binding =
self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?;
let res = binding.res();
let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?;
let (res, binding) = match ls_binding {
LexicalScopeBinding::Item(binding) if binding.is_ambiguity() => {
// For ambiguous bindings we don't know all their definitions and cannot check
// whether they can be shadowed by fresh bindings or not, so force an error.
self.r.record_use(ident, ValueNS, binding, false);
return None;
}
LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
LexicalScopeBinding::Res(res) => (res, None),
};
// An immutable (no `mut`) by-value (no `ref`) binding pattern without
// a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
@ -1527,11 +1535,15 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not);
match res {
Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::Def(DefKind::Const, _)
Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
| Res::Def(DefKind::Const, _)
| Res::Def(DefKind::ConstParam, _)
if is_syntactic_ambiguity =>
{
// Disambiguate in favor of a unit struct/variant or constant pattern.
self.r.record_use(ident, ValueNS, binding, false);
if let Some(binding) = binding {
self.r.record_use(ident, ValueNS, binding, false);
}
Some(res)
}
Res::Def(DefKind::Ctor(..), _)
@ -1547,23 +1559,20 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ResolutionError::BindingShadowsSomethingUnacceptable(
pat_src.descr(),
ident.name,
binding,
binding.expect("no binding for a ctor or static"),
),
);
None
}
Res::Def(DefKind::Fn, _) | Res::Err => {
Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => {
// These entities are explicitly allowed to be shadowed by fresh bindings.
None
}
res => {
span_bug!(
ident.span,
"unexpected resolution for an \
identifier in pattern: {:?}",
res
);
}
_ => span_bug!(
ident.span,
"unexpected resolution for an identifier in pattern: {:?}",
res
),
}
}

View File

@ -323,13 +323,6 @@ enum LexicalScopeBinding<'a> {
}
impl<'a> LexicalScopeBinding<'a> {
fn item(self) -> Option<&'a NameBinding<'a>> {
match self {
LexicalScopeBinding::Item(binding) => Some(binding),
_ => None,
}
}
fn res(self) -> Res {
match self {
LexicalScopeBinding::Item(binding) => binding.res(),

View File

@ -716,7 +716,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
| Res::SelfCtor(..)
| Res::Def(DefKind::Const, _)
| Res::Def(DefKind::AssocConst, _) => {} // OK
| Res::Def(DefKind::AssocConst, _)
| Res::Def(DefKind::ConstParam, _) => {} // OK
_ => bug!("unexpected pattern resolution: {:?}", res),
}

View File

@ -0,0 +1,18 @@
// Identifier pattern referring to an ambiguity item is an error (issue #46079).
mod m {
pub fn f() {}
}
use m::*;
mod n {
pub fn f() {}
}
use n::*; // OK, no conflict with `use m::*;`
fn main() {
let v = f; //~ ERROR `f` is ambiguous
match v {
f => {} //~ ERROR `f` is ambiguous
}
}

View File

@ -0,0 +1,41 @@
error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
--> $DIR/ambiguity-item.rs:14:13
|
LL | let v = f;
| ^ ambiguous name
|
note: `f` could refer to the function imported here
--> $DIR/ambiguity-item.rs:6:5
|
LL | use m::*;
| ^^^^
= help: consider adding an explicit import of `f` to disambiguate
note: `f` could also refer to the function imported here
--> $DIR/ambiguity-item.rs:11:5
|
LL | use n::*; // OK, no conflict with `use m::*;`
| ^^^^
= help: consider adding an explicit import of `f` to disambiguate
error[E0659]: `f` is ambiguous (glob import vs glob import in the same module)
--> $DIR/ambiguity-item.rs:16:9
|
LL | f => {}
| ^ ambiguous name
|
note: `f` could refer to the function imported here
--> $DIR/ambiguity-item.rs:6:5
|
LL | use m::*;
| ^^^^
= help: consider adding an explicit import of `f` to disambiguate
note: `f` could also refer to the function imported here
--> $DIR/ambiguity-item.rs:11:5
|
LL | use n::*; // OK, no conflict with `use m::*;`
| ^^^^
= help: consider adding an explicit import of `f` to disambiguate
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0659`.

View File

@ -0,0 +1,12 @@
// Identifier pattern referring to a const generic parameter is an error (issue #68853).
#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
fn check<const N: usize>() {
match 1 {
N => {} //~ ERROR const parameters cannot be referenced in patterns
_ => {}
}
}
fn main() {}

View File

@ -0,0 +1,17 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/const-param.rs:3:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0158]: const parameters cannot be referenced in patterns
--> $DIR/const-param.rs:7:9
|
LL | N => {}
| ^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0158`.