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:
David Wood 2019-05-01 14:31:27 +01:00
parent b05d5db87b
commit f47735c3dc
No known key found for this signature in database
GPG Key ID: 01760B4F9F53F154
5 changed files with 104 additions and 11 deletions

View File

@ -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 {

View File

@ -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>;`

View 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() {}

View 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`.

View 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);
}