Ensure that users cannot use generated arguments.
This commit gensyms the generated ident for replacement arguments so that users cannot refer to them. It also ensures that levenshtein distance suggestions do not suggest gensymed identifiers.
This commit is contained in:
parent
b05d5db87b
commit
f47735c3dc
@ -4183,7 +4183,7 @@ impl<'a> Resolver<'a> {
|
||||
let add_module_candidates = |module: Module<'_>, names: &mut Vec<TypoSuggestion>| {
|
||||
for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
|
||||
if let Some(binding) = resolution.borrow().binding {
|
||||
if filter_fn(binding.def()) {
|
||||
if !ident.name.is_gensymed() && filter_fn(binding.def()) {
|
||||
names.push(TypoSuggestion {
|
||||
candidate: ident.name,
|
||||
article: binding.def().article(),
|
||||
@ -4201,7 +4201,7 @@ impl<'a> Resolver<'a> {
|
||||
for rib in self.ribs[ns].iter().rev() {
|
||||
// Locals and type parameters
|
||||
for (ident, def) in &rib.bindings {
|
||||
if filter_fn(*def) {
|
||||
if !ident.name.is_gensymed() && filter_fn(*def) {
|
||||
names.push(TypoSuggestion {
|
||||
candidate: ident.name,
|
||||
article: def.article(),
|
||||
@ -4228,7 +4228,7 @@ impl<'a> Resolver<'a> {
|
||||
index: CRATE_DEF_INDEX,
|
||||
});
|
||||
|
||||
if filter_fn(crate_mod) {
|
||||
if !ident.name.is_gensymed() && filter_fn(crate_mod) {
|
||||
Some(TypoSuggestion {
|
||||
candidate: ident.name,
|
||||
article: "a",
|
||||
@ -4251,13 +4251,16 @@ impl<'a> Resolver<'a> {
|
||||
// Add primitive types to the mix
|
||||
if filter_fn(Def::PrimTy(Bool)) {
|
||||
names.extend(
|
||||
self.primitive_type_table.primitive_types.iter().map(|(name, _)| {
|
||||
TypoSuggestion {
|
||||
candidate: *name,
|
||||
article: "a",
|
||||
kind: "primitive type",
|
||||
}
|
||||
})
|
||||
self.primitive_type_table.primitive_types
|
||||
.iter()
|
||||
.filter(|(name, _)| !name.is_gensymed())
|
||||
.map(|(name, _)| {
|
||||
TypoSuggestion {
|
||||
candidate: *name,
|
||||
article: "a",
|
||||
kind: "primitive type",
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
@ -8878,7 +8878,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
// Construct a name for our temporary argument.
|
||||
let name = format!("__arg{}", index);
|
||||
let ident = Ident::from_str(&name);
|
||||
let ident = Ident::from_str(&name).gensym();
|
||||
|
||||
// Check if this is a ident pattern, if so, we can optimize and avoid adding a
|
||||
// `let <pat> = __argN;` statement, instead just adding a `let <pat> = <pat>;`
|
||||
|
11
src/test/ui/async-await-drop-order-locals-are-hidden.rs
Normal file
11
src/test/ui/async-await-drop-order-locals-are-hidden.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// edition:2018
|
||||
|
||||
#![allow(unused_variables)]
|
||||
#![feature(async_await)]
|
||||
|
||||
async fn foobar_async(x: u32, (a, _, _c): (u32, u32, u32), _: u32, _y: u32) {
|
||||
assert_eq!(__arg1, (1, 2, 3)); //~ ERROR cannot find value `__arg1` in this scope [E0425]
|
||||
assert_eq!(__arg2, 4); //~ ERROR cannot find value `__arg2` in this scope [E0425]
|
||||
}
|
||||
|
||||
fn main() {}
|
15
src/test/ui/async-await-drop-order-locals-are-hidden.stderr
Normal file
15
src/test/ui/async-await-drop-order-locals-are-hidden.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0425]: cannot find value `__arg1` in this scope
|
||||
--> $DIR/async-await-drop-order-locals-are-hidden.rs:7:16
|
||||
|
|
||||
LL | assert_eq!(__arg1, (1, 2, 3));
|
||||
| ^^^^^^ not found in this scope
|
||||
|
||||
error[E0425]: cannot find value `__arg2` in this scope
|
||||
--> $DIR/async-await-drop-order-locals-are-hidden.rs:8:16
|
||||
|
|
||||
LL | assert_eq!(__arg2, 4);
|
||||
| ^^^^^^ not found in this scope
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
64
src/test/ui/auxiliary/arc_wake.rs
Normal file
64
src/test/ui/auxiliary/arc_wake.rs
Normal file
@ -0,0 +1,64 @@
|
||||
// edition:2018
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::task::{
|
||||
Waker, RawWaker, RawWakerVTable,
|
||||
};
|
||||
|
||||
macro_rules! waker_vtable {
|
||||
($ty:ident) => {
|
||||
&RawWakerVTable::new(
|
||||
clone_arc_raw::<$ty>,
|
||||
wake_arc_raw::<$ty>,
|
||||
wake_by_ref_arc_raw::<$ty>,
|
||||
drop_arc_raw::<$ty>,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
pub trait ArcWake {
|
||||
fn wake(self: Arc<Self>);
|
||||
|
||||
fn wake_by_ref(arc_self: &Arc<Self>) {
|
||||
arc_self.clone().wake()
|
||||
}
|
||||
|
||||
fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
|
||||
{
|
||||
let ptr = Arc::into_raw(wake) as *const ();
|
||||
|
||||
unsafe {
|
||||
Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
|
||||
// Retain Arc by creating a copy
|
||||
let arc: Arc<T> = Arc::from_raw(data as *const T);
|
||||
let arc_clone = arc.clone();
|
||||
// Forget the Arcs again, so that the refcount isn't decrased
|
||||
let _ = Arc::into_raw(arc);
|
||||
let _ = Arc::into_raw(arc_clone);
|
||||
}
|
||||
|
||||
unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
|
||||
increase_refcount::<T>(data);
|
||||
RawWaker::new(data, waker_vtable!(T))
|
||||
}
|
||||
|
||||
unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
|
||||
// Drop Arc
|
||||
let _: Arc<T> = Arc::from_raw(data as *const T);
|
||||
}
|
||||
|
||||
unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
|
||||
let arc: Arc<T> = Arc::from_raw(data as *const T);
|
||||
ArcWake::wake(arc);
|
||||
}
|
||||
|
||||
unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
|
||||
let arc: Arc<T> = Arc::from_raw(data as *const T);
|
||||
ArcWake::wake_by_ref(&arc);
|
||||
let _ = Arc::into_raw(arc);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user