Skip to content

Commit 1b1fcf0

Browse files
Rollup merge of #104211 - lnicola:rust-analyzer-2022-11-09, r=lnicola
⬆️ rust-analyzer r? ``@ghost``
2 parents 985fa02 + ff118a8 commit 1b1fcf0

File tree

74 files changed

+1216
-422
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1216
-422
lines changed

src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/bug_report.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ Forum for questions: https://users.rust-lang.org/c/ide/14
1313
1414
Before submitting, please make sure that you're not running into one of these known issues:
1515
16-
1. extension doesn't load in VSCodium: #11080
17-
2. on-the-fly diagnostics are mostly unimplemented (`cargo check` diagnostics will be shown when saving a file): #3107
16+
1. on-the-fly diagnostics are mostly unimplemented (`cargo check` diagnostics will be shown when saving a file): #3107
1817
1918
Otherwise please try to provide information which will help us to fix the issue faster. Minimal reproducible examples with few dependencies are especially lovely <3.
2019
-->

src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
name: Critical Nightly Regression
33
about: You are using nightly rust-analyzer and the latest version is unusable.
44
title: ''
5-
labels: ''
6-
assignees: 'matklad'
5+
labels: 'Broken Window'
6+
assignees: ''
77

88
---
99

@@ -14,4 +14,3 @@ Please try to provide information which will help us to fix the issue faster. Mi
1414
-->
1515

1616
This is a serious regression in nightly and it's important to fix it before the next release.
17-
@matklad, please take a look.

src/tools/rust-analyzer/.github/workflows/release.yaml

+2-3
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,7 @@ jobs:
257257
- name: Publish Extension (OpenVSX, release)
258258
if: github.ref == 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer')
259259
working-directory: ./editors/code
260-
# token from https://dev.azure.com/rust-analyzer/
261-
run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix || true
260+
run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix
262261
timeout-minutes: 2
263262

264263
- name: Publish Extension (Code Marketplace, nightly)
@@ -269,5 +268,5 @@ jobs:
269268
- name: Publish Extension (OpenVSX, nightly)
270269
if: github.ref != 'refs/heads/release' && (github.repository == 'rust-analyzer/rust-analyzer' || github.repository == 'rust-lang/rust-analyzer')
271270
working-directory: ./editors/code
272-
run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix || true
271+
run: npx ovsx publish --pat ${{ secrets.OPENVSX_TOKEN }} --packagePath ../../dist/rust-analyzer-*.vsix
273272
timeout-minutes: 2

src/tools/rust-analyzer/crates/hir-def/src/pretty.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,12 @@ pub(crate) fn print_type_ref(type_ref: &TypeRef, buf: &mut dyn Write) -> fmt::Re
143143
print_type_ref(elem, buf)?;
144144
write!(buf, "]")?;
145145
}
146-
TypeRef::Fn(args_and_ret, varargs) => {
146+
TypeRef::Fn(args_and_ret, varargs, is_unsafe) => {
147147
let ((_, return_type), args) =
148148
args_and_ret.split_last().expect("TypeRef::Fn is missing return type");
149+
if *is_unsafe {
150+
write!(buf, "unsafe ")?;
151+
}
149152
write!(buf, "fn(")?;
150153
for (i, (_, typeref)) in args.iter().enumerate() {
151154
if i != 0 {

src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ pub enum TypeRef {
119119
Array(Box<TypeRef>, ConstScalarOrPath),
120120
Slice(Box<TypeRef>),
121121
/// A fn pointer. Last element of the vector is the return type.
122-
Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/),
122+
Fn(Vec<(Option<Name>, TypeRef)>, bool /*varargs*/, bool /*is_unsafe*/),
123123
ImplTrait(Vec<Interned<TypeBound>>),
124124
DynTrait(Vec<Interned<TypeBound>>),
125125
Macro(AstId<ast::MacroCall>),
@@ -229,7 +229,7 @@ impl TypeRef {
229229
Vec::new()
230230
};
231231
params.push((None, ret_ty));
232-
TypeRef::Fn(params, is_varargs)
232+
TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some())
233233
}
234234
// for types are close enough for our purposes to the inner type for now...
235235
ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()),
@@ -263,7 +263,7 @@ impl TypeRef {
263263
fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) {
264264
f(type_ref);
265265
match type_ref {
266-
TypeRef::Fn(params, _) => {
266+
TypeRef::Fn(params, _, _) => {
267267
params.iter().for_each(|(_, param_type)| go(param_type, f))
268268
}
269269
TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)),

src/tools/rust-analyzer/crates/hir-ty/src/display.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1187,8 +1187,11 @@ impl HirDisplay for TypeRef {
11871187
inner.hir_fmt(f)?;
11881188
write!(f, "]")?;
11891189
}
1190-
TypeRef::Fn(parameters, is_varargs) => {
1190+
&TypeRef::Fn(ref parameters, is_varargs, is_unsafe) => {
11911191
// FIXME: Function pointer qualifiers.
1192+
if is_unsafe {
1193+
write!(f, "unsafe ")?;
1194+
}
11921195
write!(f, "fn(")?;
11931196
if let Some(((_, return_type), function_parameters)) = parameters.split_last() {
11941197
for index in 0..function_parameters.len() {
@@ -1203,7 +1206,7 @@ impl HirDisplay for TypeRef {
12031206
write!(f, ", ")?;
12041207
}
12051208
}
1206-
if *is_varargs {
1209+
if is_varargs {
12071210
write!(f, "{}...", if parameters.len() == 1 { "" } else { ", " })?;
12081211
}
12091212
write!(f, ")")?;

src/tools/rust-analyzer/crates/hir-ty/src/infer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,7 @@ impl Expectation {
10201020
/// The primary use case is where the expected type is a fat pointer,
10211021
/// like `&[isize]`. For example, consider the following statement:
10221022
///
1023-
/// let x: &[isize] = &[1, 2, 3];
1023+
/// let x: &[isize] = &[1, 2, 3];
10241024
///
10251025
/// In this case, the expected type for the `&[1, 2, 3]` expression is
10261026
/// `&[isize]`. If however we were to say that `[1, 2, 3]` has the

src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ impl<'a> InferenceContext<'a> {
8585
let ty = match &self.body[tgt_expr] {
8686
Expr::Missing => self.err_ty(),
8787
&Expr::If { condition, then_branch, else_branch } => {
88+
let expected = &expected.adjust_for_branches(&mut self.table);
8889
self.infer_expr(
8990
condition,
9091
&Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),

src/tools/rust-analyzer/crates/hir-ty/src/lib.rs

+83-5
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ use std::sync::Arc;
3838
use chalk_ir::{
3939
fold::{Shift, TypeFoldable},
4040
interner::HasInterner,
41-
NoSolution,
41+
NoSolution, UniverseIndex,
4242
};
4343
use hir_def::{expr::ExprId, type_ref::Rawness, TypeOrConstParamId};
44+
use hir_expand::name;
4445
use itertools::Either;
46+
use traits::FnTrait;
4547
use utils::Generics;
4648

4749
use crate::{consteval::unknown_const, db::HirDatabase, utils::generics};
@@ -208,6 +210,7 @@ pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
208210
pub struct CallableSig {
209211
params_and_return: Arc<[Ty]>,
210212
is_varargs: bool,
213+
safety: Safety,
211214
}
212215

213216
has_interner!(CallableSig);
@@ -216,9 +219,14 @@ has_interner!(CallableSig);
216219
pub type PolyFnSig = Binders<CallableSig>;
217220

218221
impl CallableSig {
219-
pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig {
222+
pub fn from_params_and_return(
223+
mut params: Vec<Ty>,
224+
ret: Ty,
225+
is_varargs: bool,
226+
safety: Safety,
227+
) -> CallableSig {
220228
params.push(ret);
221-
CallableSig { params_and_return: params.into(), is_varargs }
229+
CallableSig { params_and_return: params.into(), is_varargs, safety }
222230
}
223231

224232
pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
@@ -235,13 +243,14 @@ impl CallableSig {
235243
.map(|arg| arg.assert_ty_ref(Interner).clone())
236244
.collect(),
237245
is_varargs: fn_ptr.sig.variadic,
246+
safety: fn_ptr.sig.safety,
238247
}
239248
}
240249

241250
pub fn to_fn_ptr(&self) -> FnPointer {
242251
FnPointer {
243252
num_binders: 0,
244-
sig: FnSig { abi: (), safety: Safety::Safe, variadic: self.is_varargs },
253+
sig: FnSig { abi: (), safety: self.safety, variadic: self.is_varargs },
245254
substitution: FnSubst(Substitution::from_iter(
246255
Interner,
247256
self.params_and_return.iter().cloned(),
@@ -266,7 +275,11 @@ impl TypeFoldable<Interner> for CallableSig {
266275
) -> Result<Self, E> {
267276
let vec = self.params_and_return.to_vec();
268277
let folded = vec.try_fold_with(folder, outer_binder)?;
269-
Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
278+
Ok(CallableSig {
279+
params_and_return: folded.into(),
280+
is_varargs: self.is_varargs,
281+
safety: self.safety,
282+
})
270283
}
271284
}
272285

@@ -508,3 +521,68 @@ where
508521
});
509522
Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
510523
}
524+
525+
pub fn callable_sig_from_fnonce(
526+
self_ty: &Canonical<Ty>,
527+
env: Arc<TraitEnvironment>,
528+
db: &dyn HirDatabase,
529+
) -> Option<CallableSig> {
530+
let krate = env.krate;
531+
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
532+
let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
533+
534+
let mut kinds = self_ty.binders.interned().to_vec();
535+
let b = TyBuilder::trait_ref(db, fn_once_trait);
536+
if b.remaining() != 2 {
537+
return None;
538+
}
539+
let fn_once = b
540+
.push(self_ty.value.clone())
541+
.fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
542+
.build();
543+
kinds.extend(fn_once.substitution.iter(Interner).skip(1).map(|x| {
544+
let vk = match x.data(Interner) {
545+
chalk_ir::GenericArgData::Ty(_) => {
546+
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
547+
}
548+
chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
549+
chalk_ir::GenericArgData::Const(c) => {
550+
chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
551+
}
552+
};
553+
chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
554+
}));
555+
556+
// FIXME: chalk refuses to solve `<Self as FnOnce<^0.0>>::Output == ^0.1`, so we first solve
557+
// `<Self as FnOnce<^0.0>>` and then replace `^0.0` with the concrete argument tuple.
558+
let trait_env = env.env.clone();
559+
let obligation = InEnvironment { goal: fn_once.cast(Interner), environment: trait_env };
560+
let canonical =
561+
Canonical { binders: CanonicalVarKinds::from_iter(Interner, kinds), value: obligation };
562+
let subst = match db.trait_solve(krate, canonical) {
563+
Some(Solution::Unique(vars)) => vars.value.subst,
564+
_ => return None,
565+
};
566+
let args = subst.at(Interner, self_ty.binders.interned().len()).ty(Interner)?;
567+
let params = match args.kind(Interner) {
568+
chalk_ir::TyKind::Tuple(_, subst) => {
569+
subst.iter(Interner).filter_map(|arg| arg.ty(Interner).cloned()).collect::<Vec<_>>()
570+
}
571+
_ => return None,
572+
};
573+
if params.iter().any(|ty| ty.is_unknown()) {
574+
return None;
575+
}
576+
577+
let fn_once = TyBuilder::trait_ref(db, fn_once_trait)
578+
.push(self_ty.value.clone())
579+
.push(args.clone())
580+
.build();
581+
let projection =
582+
TyBuilder::assoc_type_projection(db, output_assoc_type, Some(fn_once.substitution.clone()))
583+
.build();
584+
585+
let ret_ty = db.normalize_projection(projection, env);
586+
587+
Some(CallableSig::from_params_and_return(params, ret_ty.clone(), false, Safety::Safe))
588+
}

src/tools/rust-analyzer/crates/hir-ty/src/lower.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -227,13 +227,17 @@ impl<'a> TyLoweringContext<'a> {
227227
.intern(Interner)
228228
}
229229
TypeRef::Placeholder => TyKind::Error.intern(Interner),
230-
TypeRef::Fn(params, is_varargs) => {
230+
&TypeRef::Fn(ref params, variadic, is_unsafe) => {
231231
let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
232232
Substitution::from_iter(Interner, params.iter().map(|(_, tr)| ctx.lower_ty(tr)))
233233
});
234234
TyKind::Function(FnPointer {
235235
num_binders: 0, // FIXME lower `for<'a> fn()` correctly
236-
sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs },
236+
sig: FnSig {
237+
abi: (),
238+
safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe },
239+
variadic,
240+
},
237241
substitution: FnSubst(substs),
238242
})
239243
.intern(Interner)
@@ -1573,7 +1577,12 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
15731577
.with_type_param_mode(ParamLoweringMode::Variable);
15741578
let ret = ctx_ret.lower_ty(&data.ret_type);
15751579
let generics = generics(db.upcast(), def.into());
1576-
let sig = CallableSig::from_params_and_return(params, ret, data.is_varargs());
1580+
let sig = CallableSig::from_params_and_return(
1581+
params,
1582+
ret,
1583+
data.is_varargs(),
1584+
if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe },
1585+
);
15771586
make_binders(db, &generics, sig)
15781587
}
15791588

@@ -1617,7 +1626,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
16171626
TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
16181627
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
16191628
let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders();
1620-
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
1629+
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
16211630
}
16221631

16231632
/// Build the type of a tuple struct constructor.
@@ -1644,7 +1653,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
16441653
TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
16451654
let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
16461655
let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders();
1647-
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
1656+
Binders::new(binders, CallableSig::from_params_and_return(params, ret, false, Safety::Safe))
16481657
}
16491658

16501659
/// Build the type of a tuple enum variant constructor.

src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,23 @@ fn test() {
122122
)
123123
}
124124

125+
#[test]
126+
fn if_else_adjust_for_branches_discard_type_var() {
127+
check_no_mismatches(
128+
r#"
129+
fn test() {
130+
let f = || {
131+
if true {
132+
&""
133+
} else {
134+
""
135+
}
136+
};
137+
}
138+
"#,
139+
);
140+
}
141+
125142
#[test]
126143
fn match_first_coerce() {
127144
check_no_mismatches(
@@ -182,6 +199,22 @@ fn test() {
182199
);
183200
}
184201

202+
#[test]
203+
fn match_adjust_for_branches_discard_type_var() {
204+
check_no_mismatches(
205+
r#"
206+
fn test() {
207+
let f = || {
208+
match 0i32 {
209+
0i32 => &"",
210+
_ => "",
211+
}
212+
};
213+
}
214+
"#,
215+
);
216+
}
217+
185218
#[test]
186219
fn return_coerce_unknown() {
187220
check_types(
@@ -357,7 +390,7 @@ fn test() {
357390
let f: fn(u32) -> isize = foo;
358391
// ^^^ adjustments: Pointer(ReifyFnPointer)
359392
let f: unsafe fn(u32) -> isize = foo;
360-
// ^^^ adjustments: Pointer(ReifyFnPointer)
393+
// ^^^ adjustments: Pointer(ReifyFnPointer), Pointer(UnsafeFnPointer)
361394
}",
362395
);
363396
}
@@ -388,7 +421,10 @@ fn coerce_closure_to_fn_ptr() {
388421
check_no_mismatches(
389422
r"
390423
fn test() {
391-
let f: fn(u32) -> isize = |x| { 1 };
424+
let f: fn(u32) -> u32 = |x| x;
425+
// ^^^^^ adjustments: Pointer(ClosureFnPointer(Safe))
426+
let f: unsafe fn(u32) -> u32 = |x| x;
427+
// ^^^^^ adjustments: Pointer(ClosureFnPointer(Unsafe))
392428
}",
393429
);
394430
}

0 commit comments

Comments
 (0)