mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 13:18:47 +00:00
Support raw_ref_op's raw reference operator
This commit is contained in:
parent
190a0595a4
commit
367487fe88
12 changed files with 259 additions and 72 deletions
|
@ -28,7 +28,7 @@ use crate::{
|
|||
},
|
||||
item_scope::BuiltinShadowMode,
|
||||
path::{GenericArgs, Path},
|
||||
type_ref::{Mutability, TypeRef},
|
||||
type_ref::{Mutability, Rawness, TypeRef},
|
||||
AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
|
||||
StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
|
||||
};
|
||||
|
@ -378,8 +378,21 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
ast::Expr::RefExpr(e) => {
|
||||
let expr = self.collect_expr_opt(e.expr());
|
||||
let mutability = Mutability::from_mutable(e.mut_token().is_some());
|
||||
self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr)
|
||||
let raw_tok = e.raw_token().is_some();
|
||||
let mutability = if raw_tok {
|
||||
if e.mut_token().is_some() {
|
||||
Mutability::Mut
|
||||
} else if e.const_token().is_some() {
|
||||
Mutability::Shared
|
||||
} else {
|
||||
unreachable!("parser only remaps to raw_token() if matching mutability token follows")
|
||||
}
|
||||
} else {
|
||||
Mutability::from_mutable(e.mut_token().is_some())
|
||||
};
|
||||
let rawness = Rawness::from_raw(raw_tok);
|
||||
|
||||
self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::PrefixExpr(e) => {
|
||||
let expr = self.collect_expr_opt(e.expr());
|
||||
|
|
|
@ -19,7 +19,7 @@ use ra_syntax::ast::RangeOp;
|
|||
use crate::{
|
||||
builtin_type::{BuiltinFloat, BuiltinInt},
|
||||
path::{GenericArgs, Path},
|
||||
type_ref::{Mutability, TypeRef},
|
||||
type_ref::{Mutability, Rawness, TypeRef},
|
||||
};
|
||||
|
||||
pub type ExprId = Idx<Expr>;
|
||||
|
@ -110,6 +110,7 @@ pub enum Expr {
|
|||
},
|
||||
Ref {
|
||||
expr: ExprId,
|
||||
rawness: Rawness,
|
||||
mutability: Mutability,
|
||||
},
|
||||
Box {
|
||||
|
|
|
@ -35,6 +35,22 @@ impl Mutability {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Rawness {
|
||||
RawPtr,
|
||||
Ref,
|
||||
}
|
||||
|
||||
impl Rawness {
|
||||
pub fn from_raw(is_raw: bool) -> Rawness {
|
||||
if is_raw {
|
||||
Rawness::RawPtr
|
||||
} else {
|
||||
Rawness::Ref
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare ty::Ty
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum TypeRef {
|
||||
|
|
|
@ -17,8 +17,8 @@ use crate::{
|
|||
autoderef, method_resolution, op,
|
||||
traits::InEnvironment,
|
||||
utils::{generics, variant_data, Generics},
|
||||
ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef,
|
||||
Ty, TypeCtor, Uncertain,
|
||||
ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
|
||||
TraitRef, Ty, TypeCtor, Uncertain,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
@ -350,19 +350,28 @@ impl<'a> InferenceContext<'a> {
|
|||
// FIXME check the cast...
|
||||
cast_ty
|
||||
}
|
||||
Expr::Ref { expr, mutability } => {
|
||||
let expectation =
|
||||
if let Some((exp_inner, exp_mutability)) = &expected.ty.as_reference() {
|
||||
if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared {
|
||||
// FIXME: throw type error - expected mut reference but found shared ref,
|
||||
// which cannot be coerced
|
||||
}
|
||||
Expectation::rvalue_hint(Ty::clone(exp_inner))
|
||||
} else {
|
||||
Expectation::none()
|
||||
};
|
||||
Expr::Ref { expr, rawness, mutability } => {
|
||||
let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) =
|
||||
&expected.ty.as_reference_or_ptr()
|
||||
{
|
||||
if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared {
|
||||
// FIXME: throw type error - expected mut reference but found shared ref,
|
||||
// which cannot be coerced
|
||||
}
|
||||
if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr {
|
||||
// FIXME: throw type error - expected reference but found ptr,
|
||||
// which cannot be coerced
|
||||
}
|
||||
Expectation::rvalue_hint(Ty::clone(exp_inner))
|
||||
} else {
|
||||
Expectation::none()
|
||||
};
|
||||
let inner_ty = self.infer_expr_inner(*expr, &expectation);
|
||||
Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
|
||||
let ty = match rawness {
|
||||
Rawness::RawPtr => TypeCtor::RawPtr(*mutability),
|
||||
Rawness::Ref => TypeCtor::Ref(*mutability),
|
||||
};
|
||||
Ty::apply_one(ty, inner_ty)
|
||||
}
|
||||
Expr::Box { expr } => {
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||
|
|
|
@ -49,8 +49,10 @@ use std::sync::Arc;
|
|||
use std::{iter, mem};
|
||||
|
||||
use hir_def::{
|
||||
expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId,
|
||||
HasModule, Lookup, TraitId, TypeAliasId, TypeParamId,
|
||||
expr::ExprId,
|
||||
type_ref::{Mutability, Rawness},
|
||||
AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId,
|
||||
TypeParamId,
|
||||
};
|
||||
use ra_db::{impl_intern_key, salsa, CrateId};
|
||||
|
||||
|
@ -709,6 +711,18 @@ impl Ty {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
|
||||
match self {
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => {
|
||||
Some((parameters.as_single(), Rawness::Ref, *mutability))
|
||||
}
|
||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(mutability), parameters }) => {
|
||||
Some((parameters.as_single(), Rawness::RawPtr, *mutability))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn strip_references(&self) -> &Ty {
|
||||
let mut t: &Ty = self;
|
||||
|
||||
|
|
|
@ -116,15 +116,20 @@ fn infer_let_stmt_coerce() {
|
|||
assert_snapshot!(
|
||||
infer(r#"
|
||||
fn test() {
|
||||
let x: &[i32] = &[1];
|
||||
let x: &[isize] = &[1];
|
||||
let x: *const [isize] = &[1];
|
||||
}
|
||||
"#),
|
||||
@r###"
|
||||
11..40 '{ ...[1]; }': ()
|
||||
21..22 'x': &[i32]
|
||||
33..37 '&[1]': &[i32; _]
|
||||
34..37 '[1]': [i32; _]
|
||||
35..36 '1': i32
|
||||
11..76 '{ ...[1]; }': ()
|
||||
21..22 'x': &[isize]
|
||||
35..39 '&[1]': &[isize; _]
|
||||
36..39 '[1]': [isize; _]
|
||||
37..38 '1': isize
|
||||
49..50 'x': *const [isize]
|
||||
69..73 '&[1]': &[isize; _]
|
||||
70..73 '[1]': [isize; _]
|
||||
71..72 '1': isize
|
||||
"###);
|
||||
}
|
||||
|
||||
|
|
|
@ -384,6 +384,26 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_raw_ref() {
|
||||
assert_snapshot!(
|
||||
infer(r#"
|
||||
fn test(a: i32) {
|
||||
&raw mut a;
|
||||
&raw const a;
|
||||
}
|
||||
"#),
|
||||
@r###"
|
||||
9..10 'a': i32
|
||||
17..54 '{ ...t a; }': ()
|
||||
23..33 '&raw mut a': *mut i32
|
||||
32..33 'a': i32
|
||||
39..51 '&raw const a': *const i32
|
||||
50..51 'a': i32
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn infer_literals() {
|
||||
assert_snapshot!(
|
||||
|
|
|
@ -325,13 +325,27 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>
|
|||
let kind = match p.current() {
|
||||
// test ref_expr
|
||||
// fn foo() {
|
||||
// // reference operator
|
||||
// let _ = &1;
|
||||
// let _ = &mut &f();
|
||||
// let _ = &raw;
|
||||
// let _ = &raw.0;
|
||||
// // raw reference operator
|
||||
// let _ = &raw mut foo;
|
||||
// let _ = &raw const foo;
|
||||
// }
|
||||
T![&] => {
|
||||
m = p.start();
|
||||
p.bump(T![&]);
|
||||
p.eat(T![mut]);
|
||||
if p.at(IDENT)
|
||||
&& p.at_contextual_kw("raw")
|
||||
&& (p.nth_at(1, T![mut]) || p.nth_at(1, T![const]))
|
||||
{
|
||||
p.bump_remap(T![raw]);
|
||||
p.bump_any();
|
||||
} else {
|
||||
p.eat(T![mut]);
|
||||
}
|
||||
REF_EXPR
|
||||
}
|
||||
// test unary_expr
|
||||
|
|
|
@ -1235,6 +1235,8 @@ impl CastExpr {
|
|||
/// ```
|
||||
/// ❰ &foo ❱;
|
||||
/// ❰ &mut bar ❱;
|
||||
/// ❰ &raw const bar ❱;
|
||||
/// ❰ &raw mut bar ❱;
|
||||
/// ```
|
||||
///
|
||||
/// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators)
|
||||
|
@ -1247,6 +1249,7 @@ impl RefExpr {
|
|||
pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
|
||||
pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) }
|
||||
pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
|
||||
pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
|
||||
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
|
||||
}
|
||||
/// Prefix operator call. This is either `!` or `*` or `-`.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
SOURCE_FILE@0..52
|
||||
FN_DEF@0..51
|
||||
SOURCE_FILE@0..200
|
||||
FN_DEF@0..199
|
||||
FN_KW@0..2 "fn"
|
||||
WHITESPACE@2..3 " "
|
||||
NAME@3..6
|
||||
|
@ -8,47 +8,131 @@ SOURCE_FILE@0..52
|
|||
L_PAREN@6..7 "("
|
||||
R_PAREN@7..8 ")"
|
||||
WHITESPACE@8..9 " "
|
||||
BLOCK_EXPR@9..51
|
||||
BLOCK_EXPR@9..199
|
||||
L_CURLY@9..10 "{"
|
||||
WHITESPACE@10..15 "\n "
|
||||
LET_STMT@15..26
|
||||
LET_KW@15..18 "let"
|
||||
WHITESPACE@18..19 " "
|
||||
PLACEHOLDER_PAT@19..20
|
||||
UNDERSCORE@19..20 "_"
|
||||
WHITESPACE@20..21 " "
|
||||
EQ@21..22 "="
|
||||
WHITESPACE@22..23 " "
|
||||
REF_EXPR@23..25
|
||||
AMP@23..24 "&"
|
||||
LITERAL@24..25
|
||||
INT_NUMBER@24..25 "1"
|
||||
SEMICOLON@25..26 ";"
|
||||
WHITESPACE@26..31 "\n "
|
||||
LET_STMT@31..49
|
||||
LET_KW@31..34 "let"
|
||||
WHITESPACE@34..35 " "
|
||||
PLACEHOLDER_PAT@35..36
|
||||
UNDERSCORE@35..36 "_"
|
||||
WHITESPACE@36..37 " "
|
||||
EQ@37..38 "="
|
||||
WHITESPACE@38..39 " "
|
||||
REF_EXPR@39..48
|
||||
AMP@39..40 "&"
|
||||
MUT_KW@40..43 "mut"
|
||||
WHITESPACE@43..44 " "
|
||||
REF_EXPR@44..48
|
||||
AMP@44..45 "&"
|
||||
CALL_EXPR@45..48
|
||||
PATH_EXPR@45..46
|
||||
PATH@45..46
|
||||
PATH_SEGMENT@45..46
|
||||
NAME_REF@45..46
|
||||
IDENT@45..46 "f"
|
||||
ARG_LIST@46..48
|
||||
L_PAREN@46..47 "("
|
||||
R_PAREN@47..48 ")"
|
||||
SEMICOLON@48..49 ";"
|
||||
WHITESPACE@49..50 "\n"
|
||||
R_CURLY@50..51 "}"
|
||||
WHITESPACE@51..52 "\n"
|
||||
COMMENT@15..36 "// reference operator"
|
||||
WHITESPACE@36..41 "\n "
|
||||
LET_STMT@41..52
|
||||
LET_KW@41..44 "let"
|
||||
WHITESPACE@44..45 " "
|
||||
PLACEHOLDER_PAT@45..46
|
||||
UNDERSCORE@45..46 "_"
|
||||
WHITESPACE@46..47 " "
|
||||
EQ@47..48 "="
|
||||
WHITESPACE@48..49 " "
|
||||
REF_EXPR@49..51
|
||||
AMP@49..50 "&"
|
||||
LITERAL@50..51
|
||||
INT_NUMBER@50..51 "1"
|
||||
SEMICOLON@51..52 ";"
|
||||
WHITESPACE@52..57 "\n "
|
||||
LET_STMT@57..75
|
||||
LET_KW@57..60 "let"
|
||||
WHITESPACE@60..61 " "
|
||||
PLACEHOLDER_PAT@61..62
|
||||
UNDERSCORE@61..62 "_"
|
||||
WHITESPACE@62..63 " "
|
||||
EQ@63..64 "="
|
||||
WHITESPACE@64..65 " "
|
||||
REF_EXPR@65..74
|
||||
AMP@65..66 "&"
|
||||
MUT_KW@66..69 "mut"
|
||||
WHITESPACE@69..70 " "
|
||||
REF_EXPR@70..74
|
||||
AMP@70..71 "&"
|
||||
CALL_EXPR@71..74
|
||||
PATH_EXPR@71..72
|
||||
PATH@71..72
|
||||
PATH_SEGMENT@71..72
|
||||
NAME_REF@71..72
|
||||
IDENT@71..72 "f"
|
||||
ARG_LIST@72..74
|
||||
L_PAREN@72..73 "("
|
||||
R_PAREN@73..74 ")"
|
||||
SEMICOLON@74..75 ";"
|
||||
WHITESPACE@75..80 "\n "
|
||||
LET_STMT@80..93
|
||||
LET_KW@80..83 "let"
|
||||
WHITESPACE@83..84 " "
|
||||
PLACEHOLDER_PAT@84..85
|
||||
UNDERSCORE@84..85 "_"
|
||||
WHITESPACE@85..86 " "
|
||||
EQ@86..87 "="
|
||||
WHITESPACE@87..88 " "
|
||||
REF_EXPR@88..92
|
||||
AMP@88..89 "&"
|
||||
PATH_EXPR@89..92
|
||||
PATH@89..92
|
||||
PATH_SEGMENT@89..92
|
||||
NAME_REF@89..92
|
||||
IDENT@89..92 "raw"
|
||||
SEMICOLON@92..93 ";"
|
||||
WHITESPACE@93..98 "\n "
|
||||
LET_STMT@98..113
|
||||
LET_KW@98..101 "let"
|
||||
WHITESPACE@101..102 " "
|
||||
PLACEHOLDER_PAT@102..103
|
||||
UNDERSCORE@102..103 "_"
|
||||
WHITESPACE@103..104 " "
|
||||
EQ@104..105 "="
|
||||
WHITESPACE@105..106 " "
|
||||
REF_EXPR@106..112
|
||||
AMP@106..107 "&"
|
||||
FIELD_EXPR@107..112
|
||||
PATH_EXPR@107..110
|
||||
PATH@107..110
|
||||
PATH_SEGMENT@107..110
|
||||
NAME_REF@107..110
|
||||
IDENT@107..110 "raw"
|
||||
DOT@110..111 "."
|
||||
NAME_REF@111..112
|
||||
INT_NUMBER@111..112 "0"
|
||||
SEMICOLON@112..113 ";"
|
||||
WHITESPACE@113..118 "\n "
|
||||
COMMENT@118..143 "// raw reference oper ..."
|
||||
WHITESPACE@143..148 "\n "
|
||||
LET_STMT@148..169
|
||||
LET_KW@148..151 "let"
|
||||
WHITESPACE@151..152 " "
|
||||
PLACEHOLDER_PAT@152..153
|
||||
UNDERSCORE@152..153 "_"
|
||||
WHITESPACE@153..154 " "
|
||||
EQ@154..155 "="
|
||||
WHITESPACE@155..156 " "
|
||||
REF_EXPR@156..168
|
||||
AMP@156..157 "&"
|
||||
RAW_KW@157..160 "raw"
|
||||
WHITESPACE@160..161 " "
|
||||
MUT_KW@161..164 "mut"
|
||||
WHITESPACE@164..165 " "
|
||||
PATH_EXPR@165..168
|
||||
PATH@165..168
|
||||
PATH_SEGMENT@165..168
|
||||
NAME_REF@165..168
|
||||
IDENT@165..168 "foo"
|
||||
SEMICOLON@168..169 ";"
|
||||
WHITESPACE@169..174 "\n "
|
||||
LET_STMT@174..197
|
||||
LET_KW@174..177 "let"
|
||||
WHITESPACE@177..178 " "
|
||||
PLACEHOLDER_PAT@178..179
|
||||
UNDERSCORE@178..179 "_"
|
||||
WHITESPACE@179..180 " "
|
||||
EQ@180..181 "="
|
||||
WHITESPACE@181..182 " "
|
||||
REF_EXPR@182..196
|
||||
AMP@182..183 "&"
|
||||
RAW_KW@183..186 "raw"
|
||||
WHITESPACE@186..187 " "
|
||||
CONST_KW@187..192 "const"
|
||||
WHITESPACE@192..193 " "
|
||||
PATH_EXPR@193..196
|
||||
PATH@193..196
|
||||
PATH_SEGMENT@193..196
|
||||
NAME_REF@193..196
|
||||
IDENT@193..196 "foo"
|
||||
SEMICOLON@196..197 ";"
|
||||
WHITESPACE@197..198 "\n"
|
||||
R_CURLY@198..199 "}"
|
||||
WHITESPACE@199..200 "\n"
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
fn foo() {
|
||||
// reference operator
|
||||
let _ = &1;
|
||||
let _ = &mut &f();
|
||||
let _ = &raw;
|
||||
let _ = &raw.0;
|
||||
// raw reference operator
|
||||
let _ = &raw mut foo;
|
||||
let _ = &raw const foo;
|
||||
}
|
||||
|
|
|
@ -1153,10 +1153,12 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
|||
/// ```
|
||||
/// ❰ &foo ❱;
|
||||
/// ❰ &mut bar ❱;
|
||||
/// ❰ &raw const bar ❱;
|
||||
/// ❰ &raw mut bar ❱;
|
||||
/// ```
|
||||
///
|
||||
/// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators)
|
||||
struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr }
|
||||
struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], T![const], Expr }
|
||||
|
||||
/// Prefix operator call. This is either `!` or `*` or `-`.
|
||||
///
|
||||
|
|
Loading…
Reference in a new issue