Repository: rust-analyzer/rust-analyzer (rust)

Issue:
Auto-complete doesn't work with Arc (Deref)
Test-case:

```rust
use std::ops::Deref;
use std::sync::Arc;

struct Foo {
    a: u32,
}

impl Foo {
    fn bar(&self, a: u32) {
        println!("nights");
    }
}

struct Ref<'a, T> {
    obj: &'a T,
}

impl<'a, T> Deref for Ref<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        self.obj
    }
}

fn main() {
    let a = Arc::new(Ref { obj: &Foo { a: 8u32 } });
    a.<|>; // should show completions for `bar(&self, u32)` and `a`
}
```

rust-analyzer: `c7d37e424f1e04f87982233f97e1e9385191b7f1`

Pull request description:
Don't add `?` bounds as real bounds
closes #1709


Patch:
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index f458ea3003..0db7514658 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -3,7 +3,7 @@ use std::{collections::HashSet, error::Error, path::Path};
 use rustc_hash::FxHashMap;
 
 use ra_db::{CrateGraph, FileId, SourceRootId};
-use ra_ide_api::{AnalysisChange, AnalysisHost, FeatureFlags};
+use ra_ide_api::{AnalysisChange, AnalysisHost};
 use ra_project_model::{PackageRoot, ProjectWorkspace};
 use ra_vfs::{RootEntry, Vfs, VfsChange};
 use ra_vfs_glob::RustPackageFilterBuilder;
@@ -63,7 +63,7 @@ pub fn load(
     vfs: &mut Vfs,
 ) -> AnalysisHost {
     let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
-    let mut host = AnalysisHost::new(lru_cap, FeatureFlags::default());
+    let mut host = AnalysisHost::new(lru_cap);
     let mut analysis_change = AnalysisChange::new();
     analysis_change.set_crate_graph(crate_graph);
 
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index e6482180d5..e75337cdf7 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -75,6 +75,7 @@ impl GenericParams {
         };
         generics.parent_params = parent.map(|p| db.generic_params(p));
         let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
+        // FIXME: add `: Sized` bound for everything except for `Self` in traits
         match def {
             GenericDef::Function(it) => generics.fill(&it.source(db).ast, start),
             GenericDef::Struct(it) => generics.fill(&it.source(db).ast, start),
@@ -86,6 +87,9 @@ impl GenericParams {
                 generics.fill(&it.source(db).ast, start + 1);
             }
             GenericDef::TypeAlias(it) => generics.fill(&it.source(db).ast, start),
+            // Note that we don't add `Self` here: in `impl`s, `Self` is not a
+            // type-parameter, but rather is a type-alias for impl's target
+            // type, so this is handled by the resovler.
             GenericDef::ImplBlock(it) => generics.fill(&it.source(db).ast, start),
             GenericDef::EnumVariant(_) => {}
         }
@@ -135,6 +139,10 @@ impl GenericParams {
     }
 
     fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) {
+        if bound.has_question_mark() {
+            // FIXME: remove this bound
+            return;
+        }
         let path = bound
             .type_ref()
             .and_then(|tr| match tr {
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 2b3f984829..6878008d3f 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -118,10 +118,7 @@ impl Completions {
             .set_documentation(func.docs(ctx.db))
             .detail(detail);
         // If not an import, add parenthesis automatically.
-        if ctx.use_item_syntax.is_none()
-            && !ctx.is_call
-            && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis")
-        {
+        if ctx.use_item_syntax.is_none() && !ctx.is_call {
             tested_by!(inserts_parens_for_function_calls);
             let snippet =
                 if data.params().is_empty() || data.has_self_param() && data.params().len() == 1 {
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index f2e6b8f126..fc8252e4b5 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -7,7 +7,7 @@ use ra_db::{
 
 use crate::{
     symbol_index::{self, SymbolsDatabase},
-    FeatureFlags, LineIndex,
+    LineIndex,
 };
 
 #[salsa::database(
@@ -22,7 +22,6 @@ use crate::{
 #[derive(Debug)]
 pub(crate) struct RootDatabase {
     runtime: salsa::Runtime<RootDatabase>,
-    pub(crate) feature_flags: Arc<FeatureFlags>,
     pub(crate) last_gc: time::Instant,
     pub(crate) last_gc_check: time::Instant,
 }
@@ -47,17 +46,16 @@ impl salsa::Database for RootDatabase {
 
 impl Default for RootDatabase {
     fn default() -> RootDatabase {
-        RootDatabase::new(None, FeatureFlags::default())
+        RootDatabase::new(None)
     }
 }
 
 impl RootDatabase {
-    pub fn new(lru_capacity: Option<usize>, feature_flags: FeatureFlags) -> RootDatabase {
+    pub fn new(lru_capacity: Option<usize>) -> RootDatabase {
         let mut db = RootDatabase {
             runtime: salsa::Runtime::default(),
             last_gc: time::Instant::now(),
             last_gc_check: time::Instant::now(),
-            feature_flags: Arc::new(feature_flags),
         };
         db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
         db.set_local_roots_with_durability(Default::default(), Durability::HIGH);
@@ -76,7 +74,6 @@ impl salsa::ParallelDatabase for RootDatabase {
             runtime: self.runtime.snapshot(self),
             last_gc: self.last_gc,
             last_gc_check: self.last_gc_check,
-            feature_flags: Arc::clone(&self.feature_flags),
         })
     }
 }
diff --git a/crates/ra_ide_api/src/feature_flags.rs b/crates/ra_ide_api/src/feature_flags.rs
deleted file mode 100644
index 9f82ac71c1..0000000000
--- a/crates/ra_ide_api/src/feature_flags.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-use rustc_hash::FxHashMap;
-
-/// Feature flags hold fine-grained toggles for all *user-visible* features of
-/// rust-analyzer.
-///
-/// The exists such that users are able to disable any annoying feature (and,
-/// with many users and many features,  some features are bound to be annoying
-/// for some users)
-///
-/// Note that we purposefully use run-time checked strings, and not something
-/// checked at compile time, to keep things simple and flexible.
-///
-/// Also note that, at the moment, `FeatureFlags` also store features for
-/// `ra_lsp_server`. This should be benign layering violation.
-#[derive(Debug)]
-pub struct FeatureFlags {
-    flags: FxHashMap<String, bool>,
-}
-
-impl FeatureFlags {
-    fn new(flags: &[(&str, bool)]) -> FeatureFlags {
-        let flags = flags
-            .iter()
-            .map(|&(name, value)| {
-                check_flag_name(name);
-                (name.to_string(), value)
-            })
-            .collect();
-        FeatureFlags { flags }
-    }
-
-    pub fn set(&mut self, flag: &str, value: bool) -> Result<(), ()> {
-        match self.flags.get_mut(flag) {
-            None => Err(()),
-            Some(slot) => {
-                *slot = value;
-                Ok(())
-            }
-        }
-    }
-
-    pub fn get(&self, flag: &str) -> bool {
-        match self.flags.get(flag) {
-            None => panic!("unknown flag: {:?}", flag),
-            Some(value) => *value,
-        }
-    }
-}
-
-impl Default for FeatureFlags {
-    fn default() -> FeatureFlags {
-        FeatureFlags::new(&[
-            ("lsp.diagnostics", true),
-            ("completion.insertion.add-call-parenthesis", true),
-            ("notifications.workspace-loaded", true),
-        ])
-    }
-}
-
-fn check_flag_name(flag: &str) {
-    for c in flag.bytes() {
-        match c {
-            b'a'..=b'z' | b'-' | b'.' => (),
-            _ => panic!("flag name does not match conventions: {:?}", flag),
-        }
-    }
-}
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 514dcaf962..fa4ae4379b 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -14,7 +14,6 @@ mod db;
 pub mod mock_analysis;
 mod symbol_index;
 mod change;
-mod feature_flags;
 
 mod status;
 mod completion;
@@ -64,7 +63,6 @@ pub use crate::{
     completion::{CompletionItem, CompletionItemKind, InsertTextFormat},
     diagnostics::Severity,
     display::{file_structure, FunctionSignature, NavigationTarget, StructureNode},
-    feature_flags::FeatureFlags,
     folding_ranges::{Fold, FoldKind},
     hover::HoverResult,
     inlay_hints::{InlayHint, InlayKind},
@@ -249,13 +247,13 @@ pub struct AnalysisHost {
 
 impl Default for AnalysisHost {
     fn default() -> AnalysisHost {
-        AnalysisHost::new(None, FeatureFlags::default())
+        AnalysisHost::new(None)
     }
 }
 
 impl AnalysisHost {
-    pub fn new(lru_capcity: Option<usize>, feature_flags: FeatureFlags) -> AnalysisHost {
-        AnalysisHost { db: db::RootDatabase::new(lru_capcity, feature_flags) }
+    pub fn new(lru_capcity: Option<usize>) -> AnalysisHost {
+        AnalysisHost { db: db::RootDatabase::new(lru_capcity) }
     }
     /// Returns a snapshot of the current state, which you can query for
     /// semantic information.
@@ -263,10 +261,6 @@ impl AnalysisHost {
         Analysis { db: self.db.snapshot() }
     }
 
-    pub fn feature_flags(&self) -> &FeatureFlags {
-        &self.db.feature_flags
-    }
-
     /// Applies changes to the current state of the world. If there are
     /// outstanding snapshots, they will be canceled.
     pub fn apply_change(&mut self, change: AnalysisChange) {
@@ -325,10 +319,6 @@ impl Analysis {
         (host.analysis(), file_id)
     }
 
-    pub fn feature_flags(&self) -> &FeatureFlags {
-        &self.db.feature_flags
-    }
-
     /// Debug info about the current state of the analysis
     pub fn status(&self) -> Cancelable<String> {
         self.with_db(|db| status::status(&*db))
diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs
index 5c5ae3e18c..71838b89cd 100644
--- a/crates/ra_lsp_server/src/config.rs
+++ b/crates/ra_lsp_server/src/config.rs
@@ -1,5 +1,3 @@
-use rustc_hash::FxHashMap;
-
 use serde::{Deserialize, Deserializer};
 
 /// Client provided initialization options
@@ -14,6 +12,12 @@ pub struct ServerConfig {
     #[serde(deserialize_with = "nullable_bool_false")]
     pub publish_decorations: bool,
 
+    /// Whether or not the workspace loaded notification should be sent
+    ///
+    /// Defaults to `true`
+    #[serde(deserialize_with = "nullable_bool_true")]
+    pub show_workspace_loaded: bool,
+
     pub exclude_globs: Vec<String>,
 
     pub lru_capacity: Option<usize>,
@@ -21,19 +25,16 @@ pub struct ServerConfig {
     /// For internal usage to make integrated tests faster.
     #[serde(deserialize_with = "nullable_bool_true")]
     pub with_sysroot: bool,
-
-    /// Fine grained feature flags to disable specific features.
-    pub feature_flags: FxHashMap<String, bool>,
 }
 
 impl Default for ServerConfig {
     fn default() -> ServerConfig {
         ServerConfig {
             publish_decorations: false,
+            show_workspace_loaded: true,
             exclude_globs: Vec::new(),
             lru_capacity: None,
             with_sysroot: true,
-            feature_flags: FxHashMap::default(),
         }
     }
 }
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs
index 2c5d7c72d9..ca388e4722 100644
--- a/crates/ra_lsp_server/src/lib.rs
+++ b/crates/ra_lsp_server/src/lib.rs
@@ -11,8 +11,5 @@ mod world;
 
 pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
 pub use crate::{
-    caps::server_capabilities,
-    config::ServerConfig,
-    main_loop::LspError,
-    main_loop::{main_loop, show_message},
+    caps::server_capabilities, config::ServerConfig, main_loop::main_loop, main_loop::LspError,
 };
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index ae1392cb5d..36d4898bd9 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -1,7 +1,8 @@
 use flexi_logger::{Duplicate, Logger};
 use gen_lsp_server::{run_server, stdio_transport};
+use serde::Deserialize;
 
-use ra_lsp_server::{show_message, Result, ServerConfig};
+use ra_lsp_server::{Result, ServerConfig};
 use ra_prof;
 
 fn main() -> Result<()> {
@@ -45,23 +46,15 @@ fn main_inner() -> Result<()> {
             .filter(|workspaces| !workspaces.is_empty())
             .unwrap_or_else(|| vec![root]);
 
-        let server_config: ServerConfig = params
+        let opts = params
             .initialization_options
             .and_then(|v| {
-                serde_json::from_value(v)
-                    .map_err(|e| {
-                        log::error!("failed to deserialize config: {}", e);
-                        show_message(
-                            lsp_types::MessageType::Error,
-                            format!("failed to deserialize config: {}", e),
-                            s,
-                        );
-                    })
+                ServerConfig::deserialize(v)
+                    .map_err(|e| log::error!("failed to deserialize config: {}", e))
                     .ok()
             })
             .unwrap_or_default();
-
-        ra_lsp_server::main_loop(workspace_roots, params.capabilities, server_config, r, s)
+        ra_lsp_server::main_loop(workspace_roots, params.capabilities, opts, r, s)
     })?;
     log::info!("shutting down IO...");
     threads.join()?;
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index ce25ff162a..fcb7823861 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -9,7 +9,7 @@ use gen_lsp_server::{
     handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse,
 };
 use lsp_types::{ClientCapabilities, NumberOrString};
-use ra_ide_api::{Canceled, FeatureFlags, FileId, LibraryData};
+use ra_ide_api::{Canceled, FileId, LibraryData};
 use ra_prof::profile;
 use ra_vfs::VfsTask;
 use serde::{de::DeserializeOwned, Serialize};
@@ -56,7 +56,7 @@ pub fn main_loop(
     msg_receiver: &Receiver<RawMessage>,
     msg_sender: &Sender<RawMessage>,
 ) -> Result<()> {
-    log::info!("server_config: {:#?}", config);
+    log::debug!("server_config: {:?}", config);
     // FIXME: support dynamic workspace loading.
     let workspaces = {
         let ws_worker = workspace_loader(config.with_sysroot);
@@ -83,21 +83,6 @@ pub fn main_loop(
         .iter()
         .map(|glob| ra_vfs_glob::Glob::new(glob))
         .collect::<std::result::Result<Vec<_>, _>>()?;
-    let feature_flags = {
-        let mut ff = FeatureFlags::default();
-        for (flag, value) in config.feature_flags {
-            if let Err(_) = ff.set(flag.as_str(), value) {
-                log::error!("unknown feature flag: {:?}", flag);
-                show_message(
-                    req::MessageType::Error,
-                    format!("unknown feature flag: {:?}", flag),
-                    msg_sender,
-                );
-            }
-        }
-        ff
-    };
-    log::info!("feature_flags: {:#?}", feature_flags);
     let mut state = WorldState::new(
         ws_roots,
         workspaces,
@@ -105,13 +90,13 @@ pub fn main_loop(
         &globs,
         Options {
             publish_decorations: config.publish_decorations,
+            show_workspace_loaded: config.show_workspace_loaded,
             supports_location_link: client_caps
                 .text_document
                 .and_then(|it| it.definition)
                 .and_then(|it| it.link_support)
                 .unwrap_or(false),
         },
-        feature_flags,
     );
 
     let pool = ThreadPool::new(THREADPOOL_SIZE);
@@ -291,7 +276,7 @@ fn main_loop_inner(
             && in_flight_libraries == 0
         {
             let n_packages: usize = state.workspaces.iter().map(|it| it.n_packages()).sum();
-            if state.feature_flags().get("notifications.workspace-loaded") {
+            if state.options.show_workspace_loaded {
                 let msg = format!("workspace loaded, {} rust packages", n_packages);
                 show_message(req::MessageType::Info, msg, msg_sender);
             }
@@ -602,21 +587,18 @@ fn update_file_notifications_on_threadpool(
     subscriptions: Vec<FileId>,
 ) {
     log::trace!("updating notifications for {:?}", subscriptions);
-    let publish_diagnostics = world.feature_flags().get("lsp.diagnostics");
     pool.execute(move || {
         for file_id in subscriptions {
-            if publish_diagnostics {
-                match handlers::publish_diagnostics(&world, file_id) {
-                    Err(e) => {
-                        if !is_canceled(&e) {
-                            log::error!("failed to compute diagnostics: {:?}", e);
-                        }
-                    }
-                    Ok(params) => {
-                        let not = RawNotification::new::<req::PublishDiagnostics>(&params);
-                        sender.send(Task::Notify(not)).unwrap();
+            match handlers::publish_diagnostics(&world, file_id) {
+                Err(e) => {
+                    if !is_canceled(&e) {
+                        log::error!("failed to compute diagnostics: {:?}", e);
                     }
                 }
+                Ok(params) => {
+                    let not = RawNotification::new::<req::PublishDiagnostics>(&params);
+                    sender.send(Task::Notify(not)).unwrap();
+                }
             }
             if publish_decorations {
                 match handlers::publish_decorations(&world, file_id) {
@@ -635,11 +617,7 @@ fn update_file_notifications_on_threadpool(
     });
 }
 
-pub fn show_message(
-    typ: req::MessageType,
-    message: impl Into<String>,
-    sender: &Sender<RawMessage>,
-) {
+fn show_message(typ: req::MessageType, message: impl Into<String>, sender: &Sender<RawMessage>) {
     let message = message.into();
     let params = req::ShowMessageParams { typ, message };
     let not = RawNotification::new::<req::ShowMessage>(&params);
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index 6696dff71c..10f96812fb 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -7,8 +7,7 @@ use gen_lsp_server::ErrorCode;
 use lsp_types::Url;
 use parking_lot::RwLock;
 use ra_ide_api::{
-    Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData,
-    SourceRootId,
+    Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
 };
 use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot};
 use ra_vfs_glob::{Glob, RustPackageFilterBuilder};
@@ -23,6 +22,7 @@ use crate::{
 #[derive(Debug, Clone)]
 pub struct Options {
     pub publish_decorations: bool,
+    pub show_workspace_loaded: bool,
     pub supports_location_link: bool,
 }
 
@@ -58,7 +58,6 @@ impl WorldState {
         lru_capacity: Option<usize>,
         exclude_globs: &[Glob],
         options: Options,
-        feature_flags: FeatureFlags,
     ) -> WorldState {
         let mut change = AnalysisChange::new();
 
@@ -100,7 +99,7 @@ impl WorldState {
         }
         change.set_crate_graph(crate_graph);
 
-        let mut analysis_host = AnalysisHost::new(lru_capacity, feature_flags);
+        let mut analysis_host = AnalysisHost::new(lru_capacity);
         analysis_host.apply_change(change);
         WorldState {
             options,
@@ -185,10 +184,6 @@ impl WorldState {
     pub fn complete_request(&mut self, request: CompletedRequest) {
         self.latest_requests.write().record(request)
     }
-
-    pub fn feature_flags(&self) -> &FeatureFlags {
-        self.analysis_host.feature_flags()
-    }
 }
 
 impl WorldSnapshot {
@@ -251,8 +246,4 @@ impl WorldSnapshot {
         let path = self.vfs.read().file2path(VfsFile(file_id.0));
         self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path))
     }
-
-    pub fn feature_flags(&self) -> &FeatureFlags {
-        self.analysis.feature_flags()
-    }
 }
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 2a59cf6537..efe261fc23 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -382,6 +382,18 @@ impl ast::WherePred {
     }
 }
 
+impl ast::TypeBound {
+    pub fn question_mark_token(&self) -> Option<SyntaxToken> {
+        self.syntax()
+            .children_with_tokens()
+            .filter_map(|it| it.into_token())
+            .find(|it| it.kind() == T![?])
+    }
+    pub fn has_question_mark(&self) -> bool {
+        self.question_mark_token().is_some()
+    }
+}
+
 impl ast::TraitDef {
     pub fn is_auto(&self) -> bool {
         self.syntax().children_with_tokens().any(|t| t.kind() == T![auto])
diff --git a/editors/code/package.json b/editors/code/package.json
index 95ec6cff6f..98faf538f2 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -165,10 +165,10 @@
                     "default": false,
                     "description": "When highlighting Rust code, use a unique color per identifier"
                 },
-                "rust-analyzer.featureFlags": {
-                    "type": "object",
-                    "default": {},
-                    "description": "Fine grained feature flags to disable annoying features"
+                "rust-analyzer.showWorkspaceLoadedNotification": {
+                    "type": "boolean",
+                    "default": true,
+                    "description": "Show notification when workspace was loaded"
                 },
                 "rust-analyzer.enableEnhancedTyping": {
                     "type": "boolean",
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index 570ddca464..4df6b50ef7 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -23,7 +23,6 @@ export class Config {
     public lruCapacity: null | number = null;
     public displayInlayHints = true;
     public excludeGlobs = [];
-    public featureFlags = {};
     public cargoWatchOptions: CargoWatchOptions = {
         enableOnStartup: 'ask',
         trace: 'off',
@@ -133,8 +132,5 @@ export class Config {
         if (config.has('excludeGlobs')) {
             this.excludeGlobs = config.get('excludeGlobs') || [];
         }
-        if (config.has('featureFlags')) {
-            this.featureFlags = config.get('featureFlags') || {};
-        }
     }
 }
diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts
index 0d2a99c70d..3273d87497 100644
--- a/editors/code/src/server.ts
+++ b/editors/code/src/server.ts
@@ -45,8 +45,7 @@ export class Server {
                 showWorkspaceLoaded:
                     Server.config.showWorkspaceLoadedNotification,
                 lruCapacity: Server.config.lruCapacity,
-                excludeGlobs: Server.config.excludeGlobs,
-                featureFlags: Server.config.featureFlags
+                excludeGlobs: Server.config.excludeGlobs
             },
             traceOutputChannel
         };


Test patch:
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 6c2d857bca..57fd5492d8 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3028,6 +3028,35 @@ fn test(s: S) {
     assert_eq!(t, "{unknown}");
 }
 
+#[test]
+fn deref_trait_with_question_mark_size() {
+    let t = type_at(
+        r#"
+//- /main.rs
+#[lang = "deref"]
+trait Deref {
+    type Target;
+    fn deref(&self) -> &Self::Target;
+}
+
+struct Arc<T>;
+impl<T: ?Sized> Deref for Arc<T> {
+    type Target = T;
+}
+
+struct S;
+impl S {
+    fn foo(&self) -> u128 {}
+}
+
+fn test(s: Arc<S>) {
+    (*s, s.foo())<|>
+}
+"#,
+    );
+    assert_eq!(t, "(S, u128)");
+}
+
 #[test]
 fn obligation_from_function_clause() {
     let t = type_at(