Auto merge of #45050 - petrochenkov:ambind, r=nikomatsakis
resolve: Use same rules for disambiguating fresh bindings in `match` and `let`
Resolve `Unit` as a unit struct pattern in
```rust
struct Unit;
let Unit = x;
```
consistently with
```rust
match x {
Unit => {}
}
```
It was previously an error.
(The change also applies to unit variants and constants.)
Fixes https://users.rust-lang.org/t/e0530-cannot-shadow-unit-structs-what-in-the-earthly-what/13054
(This particular change doesn't depend on a fix for the issue mentioned in https://users.rust-lang.org/t/e0530-cannot-shadow-unit-structs-what-in-the-earthly-what/13054/4)
cc @rust-lang/lang
r? @nikomatsakis
This commit is contained in:
@@ -377,12 +377,6 @@ enum PatternSource {
|
||||
}
|
||||
|
||||
impl PatternSource {
|
||||
fn is_refutable(self) -> bool {
|
||||
match self {
|
||||
PatternSource::Match | PatternSource::IfLet | PatternSource::WhileLet => true,
|
||||
PatternSource::Let | PatternSource::For | PatternSource::FnParam => false,
|
||||
}
|
||||
}
|
||||
fn descr(self) -> &'static str {
|
||||
match self {
|
||||
PatternSource::Match => "match binding",
|
||||
@@ -2388,20 +2382,24 @@ impl<'a> Resolver<'a> {
|
||||
false, pat.span)
|
||||
.and_then(LexicalScopeBinding::item);
|
||||
let resolution = binding.map(NameBinding::def).and_then(|def| {
|
||||
let ivmode = BindingMode::ByValue(Mutability::Immutable);
|
||||
let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
|
||||
bmode != ivmode;
|
||||
let is_syntactic_ambiguity = opt_pat.is_none() &&
|
||||
bmode == BindingMode::ByValue(Mutability::Immutable);
|
||||
match def {
|
||||
Def::StructCtor(_, CtorKind::Const) |
|
||||
Def::VariantCtor(_, CtorKind::Const) |
|
||||
Def::Const(..) if !always_binding => {
|
||||
// A unit struct/variant or constant pattern.
|
||||
Def::Const(..) if is_syntactic_ambiguity => {
|
||||
// Disambiguate in favor of a unit struct/variant
|
||||
// or constant pattern.
|
||||
self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span);
|
||||
Some(PathResolution::new(def))
|
||||
}
|
||||
Def::StructCtor(..) | Def::VariantCtor(..) |
|
||||
Def::Const(..) | Def::Static(..) => {
|
||||
// A fresh binding that shadows something unacceptable.
|
||||
// This is unambiguously a fresh binding, either syntactically
|
||||
// (e.g. `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
|
||||
// to something unusable as a pattern (e.g. constructor function),
|
||||
// but we still conservatively report an error, see
|
||||
// issues/33118#issuecomment-233962221 for one reason why.
|
||||
resolve_error(
|
||||
self,
|
||||
ident.span,
|
||||
@@ -2410,7 +2408,7 @@ impl<'a> Resolver<'a> {
|
||||
);
|
||||
None
|
||||
}
|
||||
Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => {
|
||||
Def::Fn(..) | Def::Err => {
|
||||
// These entities are explicitly allowed
|
||||
// to be shadowed by fresh bindings.
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user